diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b506a39a..050611aa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [12.0.2.4] ### Added - Command ``SetOption45 1..250`` to change default bistable latching relay pulse length of 40 milliseconds +- ESP32 LVGL library from v8.2.0 to v8.3.0 ### Changed diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index aac9f4a35..7c99171d3 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -18,26 +18,23 @@ const be_ntv_func_def_t lv_style_func[] = { { "remove_prop", { (const void*) &lv_style_remove_prop, "b", "(lv.lv_style)i" } }, { "reset", { (const void*) &lv_style_reset, "", "(lv.lv_style)" } }, { "set_align", { (const void*) &lv_style_set_align, "", "(lv.lv_style)i" } }, + { "set_anim", { (const void*) &lv_style_set_anim, "", "(lv.lv_style)(lv.lv_anim)" } }, { "set_anim_speed", { (const void*) &lv_style_set_anim_speed, "", "(lv.lv_style)i" } }, { "set_anim_time", { (const void*) &lv_style_set_anim_time, "", "(lv.lv_style)i" } }, { "set_arc_color", { (const void*) &lv_style_set_arc_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_arc_color_filtered", { (const void*) &lv_style_set_arc_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_arc_img_src", { (const void*) &lv_style_set_arc_img_src, "", "(lv.lv_style)." } }, { "set_arc_opa", { (const void*) &lv_style_set_arc_opa, "", "(lv.lv_style)i" } }, { "set_arc_rounded", { (const void*) &lv_style_set_arc_rounded, "", "(lv.lv_style)b" } }, { "set_arc_width", { (const void*) &lv_style_set_arc_width, "", "(lv.lv_style)i" } }, { "set_base_dir", { (const void*) &lv_style_set_base_dir, "", "(lv.lv_style)i" } }, { "set_bg_color", { (const void*) &lv_style_set_bg_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_color_filtered", { (const void*) &lv_style_set_bg_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_bg_dither_mode", { (const void*) &lv_style_set_bg_dither_mode, "", "(lv.lv_style)i" } }, { "set_bg_grad", { (const void*) &lv_style_set_bg_grad, "", "(lv.lv_style)(lv.lv_grad_dsc)" } }, { "set_bg_grad_color", { (const void*) &lv_style_set_bg_grad_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_grad_color_filtered", { (const void*) &lv_style_set_bg_grad_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_bg_grad_dir", { (const void*) &lv_style_set_bg_grad_dir, "", "(lv.lv_style)i" } }, { "set_bg_grad_stop", { (const void*) &lv_style_set_bg_grad_stop, "", "(lv.lv_style)i" } }, { "set_bg_img_opa", { (const void*) &lv_style_set_bg_img_opa, "", "(lv.lv_style)i" } }, { "set_bg_img_recolor", { (const void*) &lv_style_set_bg_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_img_recolor_filtered", { (const void*) &lv_style_set_bg_img_recolor_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_bg_img_recolor_opa", { (const void*) &lv_style_set_bg_img_recolor_opa, "", "(lv.lv_style)i" } }, { "set_bg_img_src", { (const void*) &lv_style_set_bg_img_src, "", "(lv.lv_style)." } }, { "set_bg_img_tiled", { (const void*) &lv_style_set_bg_img_tiled, "", "(lv.lv_style)b" } }, @@ -45,7 +42,6 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_bg_opa", { (const void*) &lv_style_set_bg_opa, "", "(lv.lv_style)i" } }, { "set_blend_mode", { (const void*) &lv_style_set_blend_mode, "", "(lv.lv_style)i" } }, { "set_border_color", { (const void*) &lv_style_set_border_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_border_color_filtered", { (const void*) &lv_style_set_border_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_border_opa", { (const void*) &lv_style_set_border_opa, "", "(lv.lv_style)i" } }, { "set_border_post", { (const void*) &lv_style_set_border_post, "", "(lv.lv_style)b" } }, { "set_border_side", { (const void*) &lv_style_set_border_side, "", "(lv.lv_style)i" } }, @@ -71,11 +67,9 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_height", { (const void*) &lv_style_set_height, "", "(lv.lv_style)i" } }, { "set_img_opa", { (const void*) &lv_style_set_img_opa, "", "(lv.lv_style)i" } }, { "set_img_recolor", { (const void*) &lv_style_set_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_img_recolor_filtered", { (const void*) &lv_style_set_img_recolor_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_img_recolor_opa", { (const void*) &lv_style_set_img_recolor_opa, "", "(lv.lv_style)i" } }, { "set_layout", { (const void*) &lv_style_set_layout, "", "(lv.lv_style)i" } }, { "set_line_color", { (const void*) &lv_style_set_line_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_line_color_filtered", { (const void*) &lv_style_set_line_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_line_dash_gap", { (const void*) &lv_style_set_line_dash_gap, "", "(lv.lv_style)i" } }, { "set_line_dash_width", { (const void*) &lv_style_set_line_dash_width, "", "(lv.lv_style)i" } }, { "set_line_opa", { (const void*) &lv_style_set_line_opa, "", "(lv.lv_style)i" } }, @@ -87,7 +81,6 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_min_width", { (const void*) &lv_style_set_min_width, "", "(lv.lv_style)i" } }, { "set_opa", { (const void*) &lv_style_set_opa, "", "(lv.lv_style)i" } }, { "set_outline_color", { (const void*) &lv_style_set_outline_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_outline_color_filtered", { (const void*) &lv_style_set_outline_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_outline_opa", { (const void*) &lv_style_set_outline_opa, "", "(lv.lv_style)i" } }, { "set_outline_pad", { (const void*) &lv_style_set_outline_pad, "", "(lv.lv_style)i" } }, { "set_outline_width", { (const void*) &lv_style_set_outline_width, "", "(lv.lv_style)i" } }, @@ -102,9 +95,9 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_pad_top", { (const void*) &lv_style_set_pad_top, "", "(lv.lv_style)i" } }, { "set_pad_ver", { (const void*) &lv_style_set_pad_ver, "", "(lv.lv_style)i" } }, { "set_prop", { (const void*) &lv_style_set_prop, "", "(lv.lv_style)ii" } }, + { "set_prop_meta", { (const void*) &lv_style_set_prop_meta, "", "(lv.lv_style)ii" } }, { "set_radius", { (const void*) &lv_style_set_radius, "", "(lv.lv_style)i" } }, { "set_shadow_color", { (const void*) &lv_style_set_shadow_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_shadow_color_filtered", { (const void*) &lv_style_set_shadow_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_shadow_ofs_x", { (const void*) &lv_style_set_shadow_ofs_x, "", "(lv.lv_style)i" } }, { "set_shadow_ofs_y", { (const void*) &lv_style_set_shadow_ofs_y, "", "(lv.lv_style)i" } }, { "set_shadow_opa", { (const void*) &lv_style_set_shadow_opa, "", "(lv.lv_style)i" } }, @@ -113,7 +106,6 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_size", { (const void*) &lv_style_set_size, "", "(lv.lv_style)i" } }, { "set_text_align", { (const void*) &lv_style_set_text_align, "", "(lv.lv_style)i" } }, { "set_text_color", { (const void*) &lv_style_set_text_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_text_color_filtered", { (const void*) &lv_style_set_text_color_filtered, "", "(lv.lv_style)(lv.lv_color)" } }, { "set_text_decor", { (const void*) &lv_style_set_text_decor, "", "(lv.lv_style)i" } }, { "set_text_font", { (const void*) &lv_style_set_text_font, "", "(lv.lv_style)(lv.lv_font)" } }, { "set_text_letter_space", { (const void*) &lv_style_set_text_letter_space, "", "(lv.lv_style)i" } }, @@ -121,6 +113,8 @@ const be_ntv_func_def_t lv_style_func[] = { { "set_text_opa", { (const void*) &lv_style_set_text_opa, "", "(lv.lv_style)i" } }, { "set_transform_angle", { (const void*) &lv_style_set_transform_angle, "", "(lv.lv_style)i" } }, { "set_transform_height", { (const void*) &lv_style_set_transform_height, "", "(lv.lv_style)i" } }, + { "set_transform_pivot_x", { (const void*) &lv_style_set_transform_pivot_x, "", "(lv.lv_style)i" } }, + { "set_transform_pivot_y", { (const void*) &lv_style_set_transform_pivot_y, "", "(lv.lv_style)i" } }, { "set_transform_width", { (const void*) &lv_style_set_transform_width, "", "(lv.lv_style)i" } }, { "set_transform_zoom", { (const void*) &lv_style_set_transform_zoom, "", "(lv.lv_style)i" } }, { "set_transition", { (const void*) &lv_style_set_transition, "", "(lv.lv_style)(lv.lv_style_transition_dsc)" } }, @@ -170,12 +164,14 @@ const be_ntv_func_def_t lv_img_func[] = { const be_ntv_func_def_t lv_disp_func[] = { { "clean_dcache", { (const void*) &lv_disp_clean_dcache, "", "(lv.lv_disp)" } }, { "dpx", { (const void*) &lv_disp_dpx, "i", "(lv.lv_disp)i" } }, + { "enable_invalidation", { (const void*) &lv_disp_enable_invalidation, "", "(lv.lv_disp)b" } }, { "get_inactive_time", { (const void*) &lv_disp_get_inactive_time, "i", "(lv.lv_disp)" } }, { "get_layer_sys", { (const void*) &lv_disp_get_layer_sys, "lv.lv_obj", "(lv.lv_disp)" } }, { "get_layer_top", { (const void*) &lv_disp_get_layer_top, "lv.lv_obj", "(lv.lv_disp)" } }, { "get_scr_act", { (const void*) &lv_disp_get_scr_act, "lv.lv_obj", "(lv.lv_disp)" } }, { "get_scr_prev", { (const void*) &lv_disp_get_scr_prev, "lv.lv_obj", "(lv.lv_disp)" } }, { "get_theme", { (const void*) &lv_disp_get_theme, "lv.lv_theme", "(lv.lv_disp)" } }, + { "is_invalidation_enabled", { (const void*) &lv_disp_is_invalidation_enabled, "b", "(lv.lv_disp)" } }, { "load_scr", { (const void*) &lv_disp_load_scr, "", "(lv.lv_obj)" } }, { "set_bg_color", { (const void*) &lv_disp_set_bg_color, "", "(lv.lv_disp)(lv.lv_color)" } }, { "set_bg_image", { (const void*) &lv_disp_set_bg_image, "", "(lv.lv_disp)." } }, @@ -241,6 +237,7 @@ const be_ntv_func_def_t lv_obj_func[] = { { "get_self_width", { (const void*) &lv_obj_get_self_width, "i", "(lv.lv_obj)" } }, { "get_state", { (const void*) &lv_obj_get_state, "i", "(lv.lv_obj)" } }, { "get_style_align", { (const void*) &lv_obj_get_style_align, "i", "(lv.lv_obj)i" } }, + { "get_style_anim", { (const void*) &lv_obj_get_style_anim, "lv.lv_anim", "(lv.lv_obj)i" } }, { "get_style_anim_speed", { (const void*) &lv_obj_get_style_anim_speed, "i", "(lv.lv_obj)i" } }, { "get_style_anim_time", { (const void*) &lv_obj_get_style_anim_time, "i", "(lv.lv_obj)i" } }, { "get_style_arc_color", { (const void*) &lv_obj_get_style_arc_color, "lv.lv_color", "(lv.lv_obj)i" } }, @@ -339,6 +336,8 @@ const be_ntv_func_def_t lv_obj_func[] = { { "get_style_text_opa", { (const void*) &lv_obj_get_style_text_opa, "i", "(lv.lv_obj)i" } }, { "get_style_transform_angle", { (const void*) &lv_obj_get_style_transform_angle, "i", "(lv.lv_obj)i" } }, { "get_style_transform_height", { (const void*) &lv_obj_get_style_transform_height, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_pivot_x", { (const void*) &lv_obj_get_style_transform_pivot_x, "i", "(lv.lv_obj)i" } }, + { "get_style_transform_pivot_y", { (const void*) &lv_obj_get_style_transform_pivot_y, "i", "(lv.lv_obj)i" } }, { "get_style_transform_width", { (const void*) &lv_obj_get_style_transform_width, "i", "(lv.lv_obj)i" } }, { "get_style_transform_zoom", { (const void*) &lv_obj_get_style_transform_zoom, "i", "(lv.lv_obj)i" } }, { "get_style_transition", { (const void*) &lv_obj_get_style_transition, "lv.lv_style_transition_dsc", "(lv.lv_obj)i" } }, @@ -347,6 +346,7 @@ const be_ntv_func_def_t lv_obj_func[] = { { "get_style_width", { (const void*) &lv_obj_get_style_width, "i", "(lv.lv_obj)i" } }, { "get_style_x", { (const void*) &lv_obj_get_style_x, "i", "(lv.lv_obj)i" } }, { "get_style_y", { (const void*) &lv_obj_get_style_y, "i", "(lv.lv_obj)i" } }, + { "get_transformed_area", { (const void*) &lv_obj_get_transformed_area, "", "(lv.lv_obj)(lv.lv_area)bb" } }, { "get_user_data", { (const void*) &lv_obj_get_user_data, ".", "(lv.lv_obj)" } }, { "get_width", { (const void*) &lv_obj_get_width, "i", "(lv.lv_obj)" } }, { "get_x", { (const void*) &lv_obj_get_x, "i", "(lv.lv_obj)" } }, @@ -412,6 +412,7 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_height", { (const void*) &lv_obj_set_height, "", "(lv.lv_obj)i" } }, { "set_layout", { (const void*) &lv_obj_set_layout, "", "(lv.lv_obj)i" } }, { "set_local_style_prop", { (const void*) &lv_obj_set_local_style_prop, "", "(lv.lv_obj)iii" } }, + { "set_local_style_prop_meta", { (const void*) &lv_obj_set_local_style_prop_meta, "", "(lv.lv_obj)iii" } }, { "set_parent", { (const void*) &lv_obj_set_parent, "", "(lv.lv_obj)(lv.lv_obj)" } }, { "set_pos", { (const void*) &lv_obj_set_pos, "", "(lv.lv_obj)ii" } }, { "set_scroll_dir", { (const void*) &lv_obj_set_scroll_dir, "", "(lv.lv_obj)i" } }, @@ -420,26 +421,23 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_scrollbar_mode", { (const void*) &lv_obj_set_scrollbar_mode, "", "(lv.lv_obj)i" } }, { "set_size", { (const void*) &lv_obj_set_size, "", "(lv.lv_obj)ii" } }, { "set_style_align", { (const void*) &lv_obj_set_style_align, "", "(lv.lv_obj)ii" } }, + { "set_style_anim", { (const void*) &lv_obj_set_style_anim, "", "(lv.lv_obj)(lv.lv_anim)i" } }, { "set_style_anim_speed", { (const void*) &lv_obj_set_style_anim_speed, "", "(lv.lv_obj)ii" } }, { "set_style_anim_time", { (const void*) &lv_obj_set_style_anim_time, "", "(lv.lv_obj)ii" } }, { "set_style_arc_color", { (const void*) &lv_obj_set_style_arc_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_arc_color_filtered", { (const void*) &lv_obj_set_style_arc_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_arc_img_src", { (const void*) &lv_obj_set_style_arc_img_src, "", "(lv.lv_obj).i" } }, { "set_style_arc_opa", { (const void*) &lv_obj_set_style_arc_opa, "", "(lv.lv_obj)ii" } }, { "set_style_arc_rounded", { (const void*) &lv_obj_set_style_arc_rounded, "", "(lv.lv_obj)bi" } }, { "set_style_arc_width", { (const void*) &lv_obj_set_style_arc_width, "", "(lv.lv_obj)ii" } }, { "set_style_base_dir", { (const void*) &lv_obj_set_style_base_dir, "", "(lv.lv_obj)ii" } }, { "set_style_bg_color", { (const void*) &lv_obj_set_style_bg_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_color_filtered", { (const void*) &lv_obj_set_style_bg_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_bg_dither_mode", { (const void*) &lv_obj_set_style_bg_dither_mode, "", "(lv.lv_obj)ii" } }, { "set_style_bg_grad", { (const void*) &lv_obj_set_style_bg_grad, "", "(lv.lv_obj)(lv.lv_grad_dsc)i" } }, { "set_style_bg_grad_color", { (const void*) &lv_obj_set_style_bg_grad_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_grad_color_filtered", { (const void*) &lv_obj_set_style_bg_grad_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_bg_grad_dir", { (const void*) &lv_obj_set_style_bg_grad_dir, "", "(lv.lv_obj)ii" } }, { "set_style_bg_grad_stop", { (const void*) &lv_obj_set_style_bg_grad_stop, "", "(lv.lv_obj)ii" } }, { "set_style_bg_img_opa", { (const void*) &lv_obj_set_style_bg_img_opa, "", "(lv.lv_obj)ii" } }, { "set_style_bg_img_recolor", { (const void*) &lv_obj_set_style_bg_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_img_recolor_filtered", { (const void*) &lv_obj_set_style_bg_img_recolor_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_bg_img_recolor_opa", { (const void*) &lv_obj_set_style_bg_img_recolor_opa, "", "(lv.lv_obj)ii" } }, { "set_style_bg_img_src", { (const void*) &lv_obj_set_style_bg_img_src, "", "(lv.lv_obj).i" } }, { "set_style_bg_img_tiled", { (const void*) &lv_obj_set_style_bg_img_tiled, "", "(lv.lv_obj)bi" } }, @@ -447,7 +445,6 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_bg_opa", { (const void*) &lv_obj_set_style_bg_opa, "", "(lv.lv_obj)ii" } }, { "set_style_blend_mode", { (const void*) &lv_obj_set_style_blend_mode, "", "(lv.lv_obj)ii" } }, { "set_style_border_color", { (const void*) &lv_obj_set_style_border_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_border_color_filtered", { (const void*) &lv_obj_set_style_border_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_border_opa", { (const void*) &lv_obj_set_style_border_opa, "", "(lv.lv_obj)ii" } }, { "set_style_border_post", { (const void*) &lv_obj_set_style_border_post, "", "(lv.lv_obj)bi" } }, { "set_style_border_side", { (const void*) &lv_obj_set_style_border_side, "", "(lv.lv_obj)ii" } }, @@ -473,11 +470,9 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_height", { (const void*) &lv_obj_set_style_height, "", "(lv.lv_obj)ii" } }, { "set_style_img_opa", { (const void*) &lv_obj_set_style_img_opa, "", "(lv.lv_obj)ii" } }, { "set_style_img_recolor", { (const void*) &lv_obj_set_style_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_img_recolor_filtered", { (const void*) &lv_obj_set_style_img_recolor_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_img_recolor_opa", { (const void*) &lv_obj_set_style_img_recolor_opa, "", "(lv.lv_obj)ii" } }, { "set_style_layout", { (const void*) &lv_obj_set_style_layout, "", "(lv.lv_obj)ii" } }, { "set_style_line_color", { (const void*) &lv_obj_set_style_line_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_line_color_filtered", { (const void*) &lv_obj_set_style_line_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_line_dash_gap", { (const void*) &lv_obj_set_style_line_dash_gap, "", "(lv.lv_obj)ii" } }, { "set_style_line_dash_width", { (const void*) &lv_obj_set_style_line_dash_width, "", "(lv.lv_obj)ii" } }, { "set_style_line_opa", { (const void*) &lv_obj_set_style_line_opa, "", "(lv.lv_obj)ii" } }, @@ -489,7 +484,6 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_min_width", { (const void*) &lv_obj_set_style_min_width, "", "(lv.lv_obj)ii" } }, { "set_style_opa", { (const void*) &lv_obj_set_style_opa, "", "(lv.lv_obj)ii" } }, { "set_style_outline_color", { (const void*) &lv_obj_set_style_outline_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_outline_color_filtered", { (const void*) &lv_obj_set_style_outline_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_outline_opa", { (const void*) &lv_obj_set_style_outline_opa, "", "(lv.lv_obj)ii" } }, { "set_style_outline_pad", { (const void*) &lv_obj_set_style_outline_pad, "", "(lv.lv_obj)ii" } }, { "set_style_outline_width", { (const void*) &lv_obj_set_style_outline_width, "", "(lv.lv_obj)ii" } }, @@ -505,7 +499,6 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_pad_ver", { (const void*) &lv_obj_set_style_pad_ver, "", "(lv.lv_obj)ii" } }, { "set_style_radius", { (const void*) &lv_obj_set_style_radius, "", "(lv.lv_obj)ii" } }, { "set_style_shadow_color", { (const void*) &lv_obj_set_style_shadow_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_shadow_color_filtered", { (const void*) &lv_obj_set_style_shadow_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_shadow_ofs_x", { (const void*) &lv_obj_set_style_shadow_ofs_x, "", "(lv.lv_obj)ii" } }, { "set_style_shadow_ofs_y", { (const void*) &lv_obj_set_style_shadow_ofs_y, "", "(lv.lv_obj)ii" } }, { "set_style_shadow_opa", { (const void*) &lv_obj_set_style_shadow_opa, "", "(lv.lv_obj)ii" } }, @@ -514,7 +507,6 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_size", { (const void*) &lv_obj_set_style_size, "", "(lv.lv_obj)ii" } }, { "set_style_text_align", { (const void*) &lv_obj_set_style_text_align, "", "(lv.lv_obj)ii" } }, { "set_style_text_color", { (const void*) &lv_obj_set_style_text_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_text_color_filtered", { (const void*) &lv_obj_set_style_text_color_filtered, "", "(lv.lv_obj)(lv.lv_color)i" } }, { "set_style_text_decor", { (const void*) &lv_obj_set_style_text_decor, "", "(lv.lv_obj)ii" } }, { "set_style_text_font", { (const void*) &lv_obj_set_style_text_font, "", "(lv.lv_obj)(lv.lv_font)i" } }, { "set_style_text_letter_space", { (const void*) &lv_obj_set_style_text_letter_space, "", "(lv.lv_obj)ii" } }, @@ -522,6 +514,8 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_text_opa", { (const void*) &lv_obj_set_style_text_opa, "", "(lv.lv_obj)ii" } }, { "set_style_transform_angle", { (const void*) &lv_obj_set_style_transform_angle, "", "(lv.lv_obj)ii" } }, { "set_style_transform_height", { (const void*) &lv_obj_set_style_transform_height, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_pivot_x", { (const void*) &lv_obj_set_style_transform_pivot_x, "", "(lv.lv_obj)ii" } }, + { "set_style_transform_pivot_y", { (const void*) &lv_obj_set_style_transform_pivot_y, "", "(lv.lv_obj)ii" } }, { "set_style_transform_width", { (const void*) &lv_obj_set_style_transform_width, "", "(lv.lv_obj)ii" } }, { "set_style_transform_zoom", { (const void*) &lv_obj_set_style_transform_zoom, "", "(lv.lv_obj)ii" } }, { "set_style_transition", { (const void*) &lv_obj_set_style_transition, "", "(lv.lv_obj)(lv.lv_style_transition_dsc)i" } }, @@ -535,6 +529,7 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_x", { (const void*) &lv_obj_set_x, "", "(lv.lv_obj)i" } }, { "set_y", { (const void*) &lv_obj_set_y, "", "(lv.lv_obj)i" } }, { "swap", { (const void*) &lv_obj_swap, "", "(lv.lv_obj)(lv.lv_obj)" } }, + { "transform_point", { (const void*) &lv_obj_transform_point, "", "(lv.lv_obj)(lv.lv_point)bb" } }, { "tree_walk", { (const void*) &lv_obj_tree_walk, "", "(lv.lv_obj)^lv_obj_tree_walk_cb^." } }, { "update_layout", { (const void*) &lv_obj_update_layout, "", "(lv.lv_obj)" } }, { "update_snap", { (const void*) &lv_obj_update_snap, "", "(lv.lv_obj)i" } }, @@ -548,6 +543,7 @@ const be_ntv_func_def_t lv_group_func[] = { { "focus_next", { (const void*) &lv_group_focus_next, "", "(lv.lv_group)" } }, { "focus_obj", { (const void*) &lv_group_focus_obj, "", "(lv.lv_obj)" } }, { "focus_prev", { (const void*) &lv_group_focus_prev, "", "(lv.lv_group)" } }, + { "get_edge_cb", { (const void*) &lv_group_get_edge_cb, "C", "(lv.lv_group)" } }, { "get_editing", { (const void*) &lv_group_get_editing, "b", "(lv.lv_group)" } }, { "get_focus_cb", { (const void*) &lv_group_get_focus_cb, "lv.lv_group_focus_cb", "(lv.lv_group)" } }, { "get_focused", { (const void*) &lv_group_get_focused, "lv.lv_obj", "(lv.lv_group)" } }, @@ -557,6 +553,7 @@ const be_ntv_func_def_t lv_group_func[] = { { "remove_obj", { (const void*) &lv_group_remove_obj, "", "(lv.lv_obj)" } }, { "send_data", { (const void*) &lv_group_send_data, "i", "(lv.lv_group)i" } }, { "set_default", { (const void*) &lv_group_set_default, "", "(lv.lv_group)" } }, + { "set_edge_cb", { (const void*) &lv_group_set_edge_cb, "", "(lv.lv_group)^lv_group_edge_cb^" } }, { "set_editing", { (const void*) &lv_group_set_editing, "", "(lv.lv_group)b" } }, { "set_focus_cb", { (const void*) &lv_group_set_focus_cb, "", "(lv.lv_group)^lv_group_focus_cb^" } }, { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.lv_group)(lv.lv_group_refocus_policy)" } }, @@ -706,9 +703,9 @@ const be_ntv_func_def_t lv_spinbox_func[] = { { "get_step", { (const void*) &lv_spinbox_get_step, "i", "(lv.lv_obj)" } }, { "get_value", { (const void*) &lv_spinbox_get_value, "i", "(lv.lv_obj)" } }, { "increment", { (const void*) &lv_spinbox_increment, "", "(lv.lv_obj)" } }, + { "set_cursor_pos", { (const void*) &lv_spinbox_set_cursor_pos, "", "(lv.lv_obj)i" } }, { "set_digit_format", { (const void*) &lv_spinbox_set_digit_format, "", "(lv.lv_obj)ii" } }, { "set_digit_step_direction", { (const void*) &lv_spinbox_set_digit_step_direction, "", "(lv.lv_obj)i" } }, - { "set_pos", { (const void*) &lv_spinbox_set_pos, "", "(lv.lv_obj)i" } }, { "set_range", { (const void*) &lv_spinbox_set_range, "", "(lv.lv_obj)ii" } }, { "set_rollover", { (const void*) &lv_spinbox_set_rollover, "", "(lv.lv_obj)b" } }, { "set_step", { (const void*) &lv_spinbox_set_step, "", "(lv.lv_obj)i" } }, @@ -734,6 +731,7 @@ const be_ntv_func_def_t lv_anim_func[] = { { "init", { (const void*) &lv_anim_init, "", "(lv.lv_anim)" } }, { "set_custom_exec_cb", { (const void*) &lv_anim_set_custom_exec_cb, "", "(lv.lv_anim)c" } }, { "set_delay", { (const void*) &lv_anim_set_delay, "", "(lv.lv_anim)i" } }, + { "set_deleted_cb", { (const void*) &lv_anim_set_deleted_cb, "", "(lv.lv_anim)^lv_anim_deleted_cb^" } }, { "set_early_apply", { (const void*) &lv_anim_set_early_apply, "", "(lv.lv_anim)b" } }, { "set_exec_cb", { (const void*) &lv_anim_set_exec_cb, "", "(lv.lv_anim)c" } }, { "set_get_value_cb", { (const void*) &lv_anim_set_get_value_cb, "", "(lv.lv_anim)c" } }, @@ -767,6 +765,7 @@ const be_ntv_func_def_t lv_timer_func[] = { /* `lv_arc` methods */ #ifdef BE_LV_WIDGET_ARC const be_ntv_func_def_t lv_arc_func[] = { + { "align_obj_to_angle", { (const void*) &lv_arc_align_obj_to_angle, "", "(lv.lv_obj)(lv.lv_obj)i" } }, { "get_angle_end", { (const void*) &lv_arc_get_angle_end, "i", "(lv.lv_obj)" } }, { "get_angle_start", { (const void*) &lv_arc_get_angle_start, "i", "(lv.lv_obj)" } }, { "get_bg_angle_end", { (const void*) &lv_arc_get_bg_angle_end, "i", "(lv.lv_obj)" } }, @@ -775,6 +774,7 @@ const be_ntv_func_def_t lv_arc_func[] = { { "get_min_value", { (const void*) &lv_arc_get_min_value, "i", "(lv.lv_obj)" } }, { "get_mode", { (const void*) &lv_arc_get_mode, "i", "(lv.lv_obj)" } }, { "get_value", { (const void*) &lv_arc_get_value, "i", "(lv.lv_obj)" } }, + { "rotate_obj_to_angle", { (const void*) &lv_arc_rotate_obj_to_angle, "", "(lv.lv_obj)(lv.lv_obj)i" } }, { "set_angles", { (const void*) &lv_arc_set_angles, "", "(lv.lv_obj)ii" } }, { "set_bg_angles", { (const void*) &lv_arc_set_bg_angles, "", "(lv.lv_obj)ii" } }, { "set_bg_end_angle", { (const void*) &lv_arc_set_bg_end_angle, "", "(lv.lv_obj)i" } }, @@ -872,6 +872,7 @@ const be_ntv_func_def_t lv_dropdown_func[] = { { "get_dir", { (const void*) &lv_dropdown_get_dir, "i", "(lv.lv_obj)" } }, { "get_list", { (const void*) &lv_dropdown_get_list, "lv.lv_obj", "(lv.lv_obj)" } }, { "get_option_cnt", { (const void*) &lv_dropdown_get_option_cnt, "i", "(lv.lv_obj)" } }, + { "get_option_index", { (const void*) &lv_dropdown_get_option_index, "i", "(lv.lv_obj)s" } }, { "get_options", { (const void*) &lv_dropdown_get_options, "s", "(lv.lv_obj)" } }, { "get_selected", { (const void*) &lv_dropdown_get_selected, "i", "(lv.lv_obj)" } }, { "get_selected_highlight", { (const void*) &lv_dropdown_get_selected_highlight, "b", "(lv.lv_obj)" } }, @@ -994,6 +995,7 @@ const be_ntv_func_def_t lv_textarea_func[] = { { "get_label", { (const void*) &lv_textarea_get_label, "lv.lv_obj", "(lv.lv_obj)" } }, { "get_max_length", { (const void*) &lv_textarea_get_max_length, "i", "(lv.lv_obj)" } }, { "get_one_line", { (const void*) &lv_textarea_get_one_line, "b", "(lv.lv_obj)" } }, + { "get_password_bullet", { (const void*) &lv_textarea_get_password_bullet, "s", "(lv.lv_obj)" } }, { "get_password_mode", { (const void*) &lv_textarea_get_password_mode, "b", "(lv.lv_obj)" } }, { "get_password_show_time", { (const void*) &lv_textarea_get_password_show_time, "i", "(lv.lv_obj)" } }, { "get_placeholder_text", { (const void*) &lv_textarea_get_placeholder_text, "s", "(lv.lv_obj)" } }, @@ -1006,6 +1008,7 @@ const be_ntv_func_def_t lv_textarea_func[] = { { "set_insert_replace", { (const void*) &lv_textarea_set_insert_replace, "", "(lv.lv_obj)s" } }, { "set_max_length", { (const void*) &lv_textarea_set_max_length, "", "(lv.lv_obj)i" } }, { "set_one_line", { (const void*) &lv_textarea_set_one_line, "", "(lv.lv_obj)b" } }, + { "set_password_bullet", { (const void*) &lv_textarea_set_password_bullet, "", "(lv.lv_obj)s" } }, { "set_password_mode", { (const void*) &lv_textarea_set_password_mode, "", "(lv.lv_obj)b" } }, { "set_password_show_time", { (const void*) &lv_textarea_set_password_show_time, "", "(lv.lv_obj)i" } }, { "set_placeholder_text", { (const void*) &lv_textarea_set_placeholder_text, "", "(lv.lv_obj)s" } }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c index 9f333f36b..794f07c5e 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c @@ -31,6 +31,7 @@ const be_ntv_func_def_t lv_func[] = { { "anim_del", { (const void*) &lv_anim_del, "b", ".c" } }, { "anim_del_all", { (const void*) &lv_anim_del_all, "", "" } }, { "anim_get", { (const void*) &lv_anim_get, "lv.lv_anim", ".c" } }, + { "anim_get_timer", { (const void*) &lv_anim_get_timer, "lv.lv_timer", "" } }, { "anim_refr_now", { (const void*) &lv_anim_refr_now, "", "" } }, { "anim_speed_to_time", { (const void*) &lv_anim_speed_to_time, "i", "iii" } }, { "area_align", { (const void*) &lv_area_align, "", "(lv.lv_area)(lv.lv_area)iii" } }, @@ -80,6 +81,10 @@ const be_ntv_func_def_t lv_func[] = { { "draw_init", { (const void*) &lv_draw_init, "", "" } }, { "draw_label", { (const void*) &lv_draw_label, "", "(lv.lv_draw_ctx)(lv.lv_draw_label_dsc)(lv.lv_area)s(lv.lv_draw_label_hint)" } }, { "draw_label_dsc_init", { (const void*) &lv_draw_label_dsc_init, "", "(lv.lv_draw_label_dsc)" } }, + { "draw_layer_adjust", { (const void*) &lv_draw_layer_adjust, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)(lv.lv_draw_layer_flags)" } }, + { "draw_layer_blend", { (const void*) &lv_draw_layer_blend, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)(lv.lv_draw_img_dsc)" } }, + { "draw_layer_create", { (const void*) &lv_draw_layer_create, "lv.lv_draw_layer_ctx", "(lv.lv_draw_ctx)(lv.lv_area)(lv.lv_draw_layer_flags)" } }, + { "draw_layer_destroy", { (const void*) &lv_draw_layer_destroy, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)" } }, { "draw_letter", { (const void*) &lv_draw_letter, "", "(lv.lv_draw_ctx)(lv.lv_draw_label_dsc)(lv.lv_point)i" } }, { "draw_line", { (const void*) &lv_draw_line, "", "(lv.lv_draw_ctx)(lv.lv_draw_line_dsc)(lv.lv_point)(lv.lv_point)" } }, { "draw_line_dsc_init", { (const void*) &lv_draw_line_dsc_init, "", "(lv.lv_draw_line_dsc)" } }, @@ -101,7 +106,9 @@ const be_ntv_func_def_t lv_func[] = { { "draw_polygon", { (const void*) &lv_draw_polygon, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_point_arr)i" } }, { "draw_rect", { (const void*) &lv_draw_rect, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_area)" } }, { "draw_rect_dsc_init", { (const void*) &lv_draw_rect_dsc_init, "", "(lv.lv_draw_rect_dsc)" } }, + { "draw_transform", { (const void*) &lv_draw_transform, "", "(lv.lv_draw_ctx)(lv.lv_area).iii(lv.lv_draw_img_dsc)i(lv.lv_color)(lv.lv_opa)" } }, { "draw_triangle", { (const void*) &lv_draw_triangle, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_point_arr)" } }, + { "draw_wait_for_finish", { (const void*) &lv_draw_wait_for_finish, "", "(lv.lv_draw_ctx)" } }, { "event_register_id", { (const void*) &lv_event_register_id, "i", "" } }, { "event_send", { (const void*) &lv_event_send, "i", "(lv.lv_obj)i." } }, { "event_set_cover_res", { (const void*) &lv_event_set_cover_res, "", "(lv.lv_event)(lv.lv_cover_res)" } }, @@ -135,6 +142,7 @@ const be_ntv_func_def_t lv_func[] = { { "obj_draw_part_check_type", { (const void*) &lv_obj_draw_part_check_type, "b", "(lv.lv_obj_draw_part_dsc)(lv._lv_obj_class)i" } }, { "obj_enable_style_refresh", { (const void*) &lv_obj_enable_style_refresh, "", "b" } }, { "obj_event_base", { (const void*) &lv_obj_event_base, "i", "(lv.lv_obj_class)(lv.lv_event)" } }, + { "obj_redraw", { (const void*) &lv_obj_redraw, "", "(lv.lv_draw_ctx)(lv.lv_obj)" } }, { "obj_report_style_change", { (const void*) &lv_obj_report_style_change, "", "(lv.lv_style)" } }, { "obj_style_get_selector_part", { (const void*) &lv_obj_style_get_selector_part, "i", "i" } }, { "obj_style_get_selector_state", { (const void*) &lv_obj_style_get_selector_state, "i", "i" } }, @@ -142,15 +150,17 @@ const be_ntv_func_def_t lv_func[] = { { "palette_lighten", { (const void*) &lv_palette_lighten, "lv.lv_color", "ii" } }, { "palette_main", { (const void*) &lv_palette_main, "lv.lv_color", "i" } }, { "pct", { (const void*) &lv_pct, "i", "i" } }, + { "point_transform", { (const void*) &lv_point_transform, "", "(lv.lv_point)ii(lv.lv_point)" } }, { "rand", { (const void*) &lv_rand, "i", "ii" } }, { "refr_now", { (const void*) &lv_refr_now, "", "(lv.lv_disp)" } }, - { "refr_obj", { (const void*) &lv_refr_obj, "", "(lv.lv_draw_ctx)(lv.lv_obj)" } }, { "scr_act", { (const void*) &lv_scr_act, "lv.lv_obj", "" } }, { "scr_load", { (const void*) &lv_scr_load, "", "(lv.lv_obj)" } }, { "scr_load_anim", { (const void*) &lv_scr_load_anim, "", "(lv.lv_obj)iiib" } }, { "sqrt", { (const void*) &lv_sqrt, "", "i(lv.lv_sqrt_res)i" } }, + { "style_get_num_custom_props", { (const void*) &lv_style_get_num_custom_props, "i", "" } }, { "style_prop_get_default", { (const void*) &lv_style_prop_get_default, "i", "i" } }, - { "style_register_prop", { (const void*) &lv_style_register_prop, "i", "" } }, + { "style_prop_has_flag", { (const void*) &lv_style_prop_has_flag, "b", "ii" } }, + { "style_register_prop", { (const void*) &lv_style_register_prop, "i", "i" } }, { "style_transition_dsc_init", { (const void*) &lv_style_transition_dsc_init, "", "(lv.lv_style_transition_dsc)(lv.lv_style_prop)cii." } }, { "task_handler", { (const void*) &lv_task_handler, "i", "" } }, { "theme_apply", { (const void*) &lv_theme_apply, "", "(lv.lv_obj)" } }, @@ -166,6 +176,7 @@ const be_ntv_func_def_t lv_func[] = { { "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, { "theme_haspmota_is_inited", { (const void*) &lv_theme_haspmota_is_inited, "b", "" } }, { "theme_mono_init", { (const void*) &lv_theme_mono_init, "lv.lv_theme", "(lv.lv_disp)b(lv.lv_font)" } }, + { "theme_mono_is_inited", { (const void*) &lv_theme_mono_is_inited, "b", "" } }, { "theme_set_apply_cb", { (const void*) &lv_theme_set_apply_cb, "", "(lv.lv_theme)^lv_theme_apply_cb^" } }, { "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.lv_theme)(lv.lv_theme)" } }, { "timer_create", { (const void*) &lv_timer_create, "lv.lv_timer", "^lv_timer_cb^i." } }, @@ -173,6 +184,7 @@ const be_ntv_func_def_t lv_func[] = { { "timer_enable", { (const void*) &lv_timer_enable, "", "b" } }, { "timer_get_idle", { (const void*) &lv_timer_get_idle, "i", "" } }, { "timer_handler", { (const void*) &lv_timer_handler, "i", "" } }, + { "timer_handler_run_in_period", { (const void*) &lv_timer_handler_run_in_period, "i", "i" } }, { "trigo_cos", { (const void*) &lv_trigo_cos, "i", "i" } }, { "trigo_sin", { (const void*) &lv_trigo_sin, "i", "i" } }, @@ -311,6 +323,9 @@ const be_const_member_t lv0_constants[] = { { "DITHER_ERR_DIFF", be_cconst_int(LV_DITHER_ERR_DIFF) }, { "DITHER_NONE", be_cconst_int(LV_DITHER_NONE) }, { "DITHER_ORDERED", be_cconst_int(LV_DITHER_ORDERED) }, + { "DRAW_LAYER_FLAG_CAN_SUBDIVIDE", be_cconst_int(LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) }, + { "DRAW_LAYER_FLAG_HAS_ALPHA", be_cconst_int(LV_DRAW_LAYER_FLAG_HAS_ALPHA) }, + { "DRAW_LAYER_FLAG_NONE", be_cconst_int(LV_DRAW_LAYER_FLAG_NONE) }, { "DRAW_MASK_LINE_SIDE_BOTTOM", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_BOTTOM) }, { "DRAW_MASK_LINE_SIDE_LEFT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_LEFT) }, { "DRAW_MASK_LINE_SIDE_RIGHT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_RIGHT) }, @@ -439,6 +454,12 @@ const be_const_member_t lv0_constants[] = { { "IMG_CF_RAW", be_cconst_int(LV_IMG_CF_RAW) }, { "IMG_CF_RAW_ALPHA", be_cconst_int(LV_IMG_CF_RAW_ALPHA) }, { "IMG_CF_RAW_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_RAW_CHROMA_KEYED) }, + { "IMG_CF_RGB565", be_cconst_int(LV_IMG_CF_RGB565) }, + { "IMG_CF_RGB565A8", be_cconst_int(LV_IMG_CF_RGB565A8) }, + { "IMG_CF_RGB888", be_cconst_int(LV_IMG_CF_RGB888) }, + { "IMG_CF_RGBA5658", be_cconst_int(LV_IMG_CF_RGBA5658) }, + { "IMG_CF_RGBA8888", be_cconst_int(LV_IMG_CF_RGBA8888) }, + { "IMG_CF_RGBX8888", be_cconst_int(LV_IMG_CF_RGBX8888) }, { "IMG_CF_TRUE_COLOR", be_cconst_int(LV_IMG_CF_TRUE_COLOR) }, { "IMG_CF_TRUE_COLOR_ALPHA", be_cconst_int(LV_IMG_CF_TRUE_COLOR_ALPHA) }, { "IMG_CF_TRUE_COLOR_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) }, @@ -477,6 +498,9 @@ const be_const_member_t lv0_constants[] = { { "LABEL_LONG_WRAP", be_cconst_int(LV_LABEL_LONG_WRAP) }, { "LABEL_POS_LAST", be_cconst_int(LV_LABEL_POS_LAST) }, { "LABEL_TEXT_SELECTION_OFF", be_cconst_int(LV_LABEL_TEXT_SELECTION_OFF) }, + { "LAYER_TYPE_NONE", be_cconst_int(LV_LAYER_TYPE_NONE) }, + { "LAYER_TYPE_SIMPLE", be_cconst_int(LV_LAYER_TYPE_SIMPLE) }, + { "LAYER_TYPE_TRANSFORM", be_cconst_int(LV_LAYER_TYPE_TRANSFORM) }, { "LED_DRAW_PART_RECTANGLE", be_cconst_int(LV_LED_DRAW_PART_RECTANGLE) }, { "LOG_LEVEL_ERROR", be_cconst_int(LV_LOG_LEVEL_ERROR) }, { "LOG_LEVEL_INFO", be_cconst_int(LV_LOG_LEVEL_INFO) }, @@ -596,12 +620,18 @@ const be_const_member_t lv0_constants[] = { { "SCROLL_SNAP_END", be_cconst_int(LV_SCROLL_SNAP_END) }, { "SCROLL_SNAP_NONE", be_cconst_int(LV_SCROLL_SNAP_NONE) }, { "SCROLL_SNAP_START", be_cconst_int(LV_SCROLL_SNAP_START) }, + { "SCR_LOAD_ANIM_FADE_IN", be_cconst_int(LV_SCR_LOAD_ANIM_FADE_IN) }, { "SCR_LOAD_ANIM_FADE_ON", be_cconst_int(LV_SCR_LOAD_ANIM_FADE_ON) }, + { "SCR_LOAD_ANIM_FADE_OUT", be_cconst_int(LV_SCR_LOAD_ANIM_FADE_OUT) }, { "SCR_LOAD_ANIM_MOVE_BOTTOM", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_BOTTOM) }, { "SCR_LOAD_ANIM_MOVE_LEFT", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_LEFT) }, { "SCR_LOAD_ANIM_MOVE_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_RIGHT) }, { "SCR_LOAD_ANIM_MOVE_TOP", be_cconst_int(LV_SCR_LOAD_ANIM_MOVE_TOP) }, { "SCR_LOAD_ANIM_NONE", be_cconst_int(LV_SCR_LOAD_ANIM_NONE) }, + { "SCR_LOAD_ANIM_OUT_BOTTOM", be_cconst_int(LV_SCR_LOAD_ANIM_OUT_BOTTOM) }, + { "SCR_LOAD_ANIM_OUT_LEFT", be_cconst_int(LV_SCR_LOAD_ANIM_OUT_LEFT) }, + { "SCR_LOAD_ANIM_OUT_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_OUT_RIGHT) }, + { "SCR_LOAD_ANIM_OUT_TOP", be_cconst_int(LV_SCR_LOAD_ANIM_OUT_TOP) }, { "SCR_LOAD_ANIM_OVER_BOTTOM", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_BOTTOM) }, { "SCR_LOAD_ANIM_OVER_LEFT", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_LEFT) }, { "SCR_LOAD_ANIM_OVER_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_RIGHT) }, @@ -632,26 +662,23 @@ const be_const_member_t lv0_constants[] = { { "STATE_USER_3", be_cconst_int(LV_STATE_USER_3) }, { "STATE_USER_4", be_cconst_int(LV_STATE_USER_4) }, { "STYLE_ALIGN", be_cconst_int(LV_STYLE_ALIGN) }, + { "STYLE_ANIM", be_cconst_int(LV_STYLE_ANIM) }, { "STYLE_ANIM_SPEED", be_cconst_int(LV_STYLE_ANIM_SPEED) }, { "STYLE_ANIM_TIME", be_cconst_int(LV_STYLE_ANIM_TIME) }, { "STYLE_ARC_COLOR", be_cconst_int(LV_STYLE_ARC_COLOR) }, - { "STYLE_ARC_COLOR_FILTERED", be_cconst_int(LV_STYLE_ARC_COLOR_FILTERED) }, { "STYLE_ARC_IMG_SRC", be_cconst_int(LV_STYLE_ARC_IMG_SRC) }, { "STYLE_ARC_OPA", be_cconst_int(LV_STYLE_ARC_OPA) }, { "STYLE_ARC_ROUNDED", be_cconst_int(LV_STYLE_ARC_ROUNDED) }, { "STYLE_ARC_WIDTH", be_cconst_int(LV_STYLE_ARC_WIDTH) }, { "STYLE_BASE_DIR", be_cconst_int(LV_STYLE_BASE_DIR) }, { "STYLE_BG_COLOR", be_cconst_int(LV_STYLE_BG_COLOR) }, - { "STYLE_BG_COLOR_FILTERED", be_cconst_int(LV_STYLE_BG_COLOR_FILTERED) }, { "STYLE_BG_DITHER_MODE", be_cconst_int(LV_STYLE_BG_DITHER_MODE) }, { "STYLE_BG_GRAD", be_cconst_int(LV_STYLE_BG_GRAD) }, { "STYLE_BG_GRAD_COLOR", be_cconst_int(LV_STYLE_BG_GRAD_COLOR) }, - { "STYLE_BG_GRAD_COLOR_FILTERED", be_cconst_int(LV_STYLE_BG_GRAD_COLOR_FILTERED) }, { "STYLE_BG_GRAD_DIR", be_cconst_int(LV_STYLE_BG_GRAD_DIR) }, { "STYLE_BG_GRAD_STOP", be_cconst_int(LV_STYLE_BG_GRAD_STOP) }, { "STYLE_BG_IMG_OPA", be_cconst_int(LV_STYLE_BG_IMG_OPA) }, { "STYLE_BG_IMG_RECOLOR", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR) }, - { "STYLE_BG_IMG_RECOLOR_FILTERED", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR_FILTERED) }, { "STYLE_BG_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR_OPA) }, { "STYLE_BG_IMG_SRC", be_cconst_int(LV_STYLE_BG_IMG_SRC) }, { "STYLE_BG_IMG_TILED", be_cconst_int(LV_STYLE_BG_IMG_TILED) }, @@ -659,7 +686,6 @@ const be_const_member_t lv0_constants[] = { { "STYLE_BG_OPA", be_cconst_int(LV_STYLE_BG_OPA) }, { "STYLE_BLEND_MODE", be_cconst_int(LV_STYLE_BLEND_MODE) }, { "STYLE_BORDER_COLOR", be_cconst_int(LV_STYLE_BORDER_COLOR) }, - { "STYLE_BORDER_COLOR_FILTERED", be_cconst_int(LV_STYLE_BORDER_COLOR_FILTERED) }, { "STYLE_BORDER_OPA", be_cconst_int(LV_STYLE_BORDER_OPA) }, { "STYLE_BORDER_POST", be_cconst_int(LV_STYLE_BORDER_POST) }, { "STYLE_BORDER_SIDE", be_cconst_int(LV_STYLE_BORDER_SIDE) }, @@ -670,11 +696,9 @@ const be_const_member_t lv0_constants[] = { { "STYLE_HEIGHT", be_cconst_int(LV_STYLE_HEIGHT) }, { "STYLE_IMG_OPA", be_cconst_int(LV_STYLE_IMG_OPA) }, { "STYLE_IMG_RECOLOR", be_cconst_int(LV_STYLE_IMG_RECOLOR) }, - { "STYLE_IMG_RECOLOR_FILTERED", be_cconst_int(LV_STYLE_IMG_RECOLOR_FILTERED) }, { "STYLE_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_IMG_RECOLOR_OPA) }, { "STYLE_LAYOUT", be_cconst_int(LV_STYLE_LAYOUT) }, { "STYLE_LINE_COLOR", be_cconst_int(LV_STYLE_LINE_COLOR) }, - { "STYLE_LINE_COLOR_FILTERED", be_cconst_int(LV_STYLE_LINE_COLOR_FILTERED) }, { "STYLE_LINE_DASH_GAP", be_cconst_int(LV_STYLE_LINE_DASH_GAP) }, { "STYLE_LINE_DASH_WIDTH", be_cconst_int(LV_STYLE_LINE_DASH_WIDTH) }, { "STYLE_LINE_OPA", be_cconst_int(LV_STYLE_LINE_OPA) }, @@ -686,7 +710,6 @@ const be_const_member_t lv0_constants[] = { { "STYLE_MIN_WIDTH", be_cconst_int(LV_STYLE_MIN_WIDTH) }, { "STYLE_OPA", be_cconst_int(LV_STYLE_OPA) }, { "STYLE_OUTLINE_COLOR", be_cconst_int(LV_STYLE_OUTLINE_COLOR) }, - { "STYLE_OUTLINE_COLOR_FILTERED", be_cconst_int(LV_STYLE_OUTLINE_COLOR_FILTERED) }, { "STYLE_OUTLINE_OPA", be_cconst_int(LV_STYLE_OUTLINE_OPA) }, { "STYLE_OUTLINE_PAD", be_cconst_int(LV_STYLE_OUTLINE_PAD) }, { "STYLE_OUTLINE_WIDTH", be_cconst_int(LV_STYLE_OUTLINE_WIDTH) }, @@ -699,8 +722,10 @@ const be_const_member_t lv0_constants[] = { { "STYLE_PROP_ANY", be_cconst_int(LV_STYLE_PROP_ANY) }, { "STYLE_PROP_INV", be_cconst_int(LV_STYLE_PROP_INV) }, { "STYLE_RADIUS", be_cconst_int(LV_STYLE_RADIUS) }, + { "STYLE_RES_FOUND", be_cconst_int(LV_STYLE_RES_FOUND) }, + { "STYLE_RES_INHERIT", be_cconst_int(LV_STYLE_RES_INHERIT) }, + { "STYLE_RES_NOT_FOUND", be_cconst_int(LV_STYLE_RES_NOT_FOUND) }, { "STYLE_SHADOW_COLOR", be_cconst_int(LV_STYLE_SHADOW_COLOR) }, - { "STYLE_SHADOW_COLOR_FILTERED", be_cconst_int(LV_STYLE_SHADOW_COLOR_FILTERED) }, { "STYLE_SHADOW_OFS_X", be_cconst_int(LV_STYLE_SHADOW_OFS_X) }, { "STYLE_SHADOW_OFS_Y", be_cconst_int(LV_STYLE_SHADOW_OFS_Y) }, { "STYLE_SHADOW_OPA", be_cconst_int(LV_STYLE_SHADOW_OPA) }, @@ -708,7 +733,6 @@ const be_const_member_t lv0_constants[] = { { "STYLE_SHADOW_WIDTH", be_cconst_int(LV_STYLE_SHADOW_WIDTH) }, { "STYLE_TEXT_ALIGN", be_cconst_int(LV_STYLE_TEXT_ALIGN) }, { "STYLE_TEXT_COLOR", be_cconst_int(LV_STYLE_TEXT_COLOR) }, - { "STYLE_TEXT_COLOR_FILTERED", be_cconst_int(LV_STYLE_TEXT_COLOR_FILTERED) }, { "STYLE_TEXT_DECOR", be_cconst_int(LV_STYLE_TEXT_DECOR) }, { "STYLE_TEXT_FONT", be_cconst_int(LV_STYLE_TEXT_FONT) }, { "STYLE_TEXT_LETTER_SPACE", be_cconst_int(LV_STYLE_TEXT_LETTER_SPACE) }, @@ -716,6 +740,8 @@ const be_const_member_t lv0_constants[] = { { "STYLE_TEXT_OPA", be_cconst_int(LV_STYLE_TEXT_OPA) }, { "STYLE_TRANSFORM_ANGLE", be_cconst_int(LV_STYLE_TRANSFORM_ANGLE) }, { "STYLE_TRANSFORM_HEIGHT", be_cconst_int(LV_STYLE_TRANSFORM_HEIGHT) }, + { "STYLE_TRANSFORM_PIVOT_X", be_cconst_int(LV_STYLE_TRANSFORM_PIVOT_X) }, + { "STYLE_TRANSFORM_PIVOT_Y", be_cconst_int(LV_STYLE_TRANSFORM_PIVOT_Y) }, { "STYLE_TRANSFORM_WIDTH", be_cconst_int(LV_STYLE_TRANSFORM_WIDTH) }, { "STYLE_TRANSFORM_ZOOM", be_cconst_int(LV_STYLE_TRANSFORM_ZOOM) }, { "STYLE_TRANSITION", be_cconst_int(LV_STYLE_TRANSITION) }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c index b5438ab72..581fce9a4 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c @@ -48,6 +48,7 @@ extern int lvbe_style_set_grid_cell_y_align(bvm *vm); extern int lvbe_style_reset(bvm *vm); extern int lvbe_style_remove_prop(bvm *vm); extern int lvbe_style_set_prop(bvm *vm); +extern int lvbe_style_set_prop_meta(bvm *vm); extern int lvbe_style_get_prop(bvm *vm); extern int lvbe_style_get_prop_inlined(bvm *vm); extern int lvbe_style_is_empty(bvm *vm); @@ -71,6 +72,8 @@ extern int lvbe_style_set_translate_x(bvm *vm); extern int lvbe_style_set_translate_y(bvm *vm); extern int lvbe_style_set_transform_zoom(bvm *vm); extern int lvbe_style_set_transform_angle(bvm *vm); +extern int lvbe_style_set_transform_pivot_x(bvm *vm); +extern int lvbe_style_set_transform_pivot_y(bvm *vm); extern int lvbe_style_set_pad_top(bvm *vm); extern int lvbe_style_set_pad_bottom(bvm *vm); extern int lvbe_style_set_pad_left(bvm *vm); @@ -78,10 +81,8 @@ extern int lvbe_style_set_pad_right(bvm *vm); extern int lvbe_style_set_pad_row(bvm *vm); extern int lvbe_style_set_pad_column(bvm *vm); extern int lvbe_style_set_bg_color(bvm *vm); -extern int lvbe_style_set_bg_color_filtered(bvm *vm); extern int lvbe_style_set_bg_opa(bvm *vm); extern int lvbe_style_set_bg_grad_color(bvm *vm); -extern int lvbe_style_set_bg_grad_color_filtered(bvm *vm); extern int lvbe_style_set_bg_grad_dir(bvm *vm); extern int lvbe_style_set_bg_main_stop(bvm *vm); extern int lvbe_style_set_bg_grad_stop(bvm *vm); @@ -90,18 +91,15 @@ extern int lvbe_style_set_bg_dither_mode(bvm *vm); extern int lvbe_style_set_bg_img_src(bvm *vm); extern int lvbe_style_set_bg_img_opa(bvm *vm); extern int lvbe_style_set_bg_img_recolor(bvm *vm); -extern int lvbe_style_set_bg_img_recolor_filtered(bvm *vm); extern int lvbe_style_set_bg_img_recolor_opa(bvm *vm); extern int lvbe_style_set_bg_img_tiled(bvm *vm); extern int lvbe_style_set_border_color(bvm *vm); -extern int lvbe_style_set_border_color_filtered(bvm *vm); extern int lvbe_style_set_border_opa(bvm *vm); extern int lvbe_style_set_border_width(bvm *vm); extern int lvbe_style_set_border_side(bvm *vm); extern int lvbe_style_set_border_post(bvm *vm); extern int lvbe_style_set_outline_width(bvm *vm); extern int lvbe_style_set_outline_color(bvm *vm); -extern int lvbe_style_set_outline_color_filtered(bvm *vm); extern int lvbe_style_set_outline_opa(bvm *vm); extern int lvbe_style_set_outline_pad(bvm *vm); extern int lvbe_style_set_shadow_width(bvm *vm); @@ -109,27 +107,22 @@ extern int lvbe_style_set_shadow_ofs_x(bvm *vm); extern int lvbe_style_set_shadow_ofs_y(bvm *vm); extern int lvbe_style_set_shadow_spread(bvm *vm); extern int lvbe_style_set_shadow_color(bvm *vm); -extern int lvbe_style_set_shadow_color_filtered(bvm *vm); extern int lvbe_style_set_shadow_opa(bvm *vm); extern int lvbe_style_set_img_opa(bvm *vm); extern int lvbe_style_set_img_recolor(bvm *vm); -extern int lvbe_style_set_img_recolor_filtered(bvm *vm); extern int lvbe_style_set_img_recolor_opa(bvm *vm); extern int lvbe_style_set_line_width(bvm *vm); extern int lvbe_style_set_line_dash_width(bvm *vm); extern int lvbe_style_set_line_dash_gap(bvm *vm); extern int lvbe_style_set_line_rounded(bvm *vm); extern int lvbe_style_set_line_color(bvm *vm); -extern int lvbe_style_set_line_color_filtered(bvm *vm); extern int lvbe_style_set_line_opa(bvm *vm); extern int lvbe_style_set_arc_width(bvm *vm); extern int lvbe_style_set_arc_rounded(bvm *vm); extern int lvbe_style_set_arc_color(bvm *vm); -extern int lvbe_style_set_arc_color_filtered(bvm *vm); extern int lvbe_style_set_arc_opa(bvm *vm); extern int lvbe_style_set_arc_img_src(bvm *vm); extern int lvbe_style_set_text_color(bvm *vm); -extern int lvbe_style_set_text_color_filtered(bvm *vm); extern int lvbe_style_set_text_opa(bvm *vm); extern int lvbe_style_set_text_font(bvm *vm); extern int lvbe_style_set_text_letter_space(bvm *vm); @@ -141,6 +134,7 @@ extern int lvbe_style_set_clip_corner(bvm *vm); extern int lvbe_style_set_opa(bvm *vm); extern int lvbe_style_set_color_filter_dsc(bvm *vm); extern int lvbe_style_set_color_filter_opa(bvm *vm); +extern int lvbe_style_set_anim(bvm *vm); extern int lvbe_style_set_anim_time(bvm *vm); extern int lvbe_style_set_anim_speed(bvm *vm); extern int lvbe_style_set_transition(bvm *vm); @@ -188,6 +182,8 @@ extern int lvbe_disp_set_bg_opa(bvm *vm); extern int lvbe_disp_get_inactive_time(bvm *vm); extern int lvbe_disp_trig_activity(bvm *vm); extern int lvbe_disp_clean_dcache(bvm *vm); +extern int lvbe_disp_enable_invalidation(bvm *vm); +extern int lvbe_disp_is_invalidation_enabled(bvm *vm); extern int lvbe_disp_dpx(bvm *vm); /* `lv_obj` external functions definitions */ @@ -259,6 +255,8 @@ extern int lvbe_obj_refresh_self_size(bvm *vm); extern int lvbe_obj_refr_pos(bvm *vm); extern int lvbe_obj_move_to(bvm *vm); extern int lvbe_obj_move_children_by(bvm *vm); +extern int lvbe_obj_transform_point(bvm *vm); +extern int lvbe_obj_get_transformed_area(bvm *vm); extern int lvbe_obj_invalidate_area(bvm *vm); extern int lvbe_obj_invalidate(bvm *vm); extern int lvbe_obj_area_is_visible(bvm *vm); @@ -299,6 +297,7 @@ extern int lvbe_obj_remove_style_all(bvm *vm); extern int lvbe_obj_refresh_style(bvm *vm); extern int lvbe_obj_get_style_prop(bvm *vm); extern int lvbe_obj_set_local_style_prop(bvm *vm); +extern int lvbe_obj_set_local_style_prop_meta(bvm *vm); extern int lvbe_obj_get_local_style_prop(bvm *vm); extern int lvbe_obj_remove_local_style_prop(bvm *vm); extern int lvbe_obj_fade_in(bvm *vm); @@ -324,6 +323,8 @@ extern int lvbe_obj_get_style_translate_x(bvm *vm); extern int lvbe_obj_get_style_translate_y(bvm *vm); extern int lvbe_obj_get_style_transform_zoom(bvm *vm); extern int lvbe_obj_get_style_transform_angle(bvm *vm); +extern int lvbe_obj_get_style_transform_pivot_x(bvm *vm); +extern int lvbe_obj_get_style_transform_pivot_y(bvm *vm); extern int lvbe_obj_get_style_pad_top(bvm *vm); extern int lvbe_obj_get_style_pad_bottom(bvm *vm); extern int lvbe_obj_get_style_pad_left(bvm *vm); @@ -394,6 +395,7 @@ extern int lvbe_obj_get_style_clip_corner(bvm *vm); extern int lvbe_obj_get_style_opa(bvm *vm); extern int lvbe_obj_get_style_color_filter_dsc(bvm *vm); extern int lvbe_obj_get_style_color_filter_opa(bvm *vm); +extern int lvbe_obj_get_style_anim(bvm *vm); extern int lvbe_obj_get_style_anim_time(bvm *vm); extern int lvbe_obj_get_style_anim_speed(bvm *vm); extern int lvbe_obj_get_style_transition(bvm *vm); @@ -415,6 +417,8 @@ extern int lvbe_obj_set_style_translate_x(bvm *vm); extern int lvbe_obj_set_style_translate_y(bvm *vm); extern int lvbe_obj_set_style_transform_zoom(bvm *vm); extern int lvbe_obj_set_style_transform_angle(bvm *vm); +extern int lvbe_obj_set_style_transform_pivot_x(bvm *vm); +extern int lvbe_obj_set_style_transform_pivot_y(bvm *vm); extern int lvbe_obj_set_style_pad_top(bvm *vm); extern int lvbe_obj_set_style_pad_bottom(bvm *vm); extern int lvbe_obj_set_style_pad_left(bvm *vm); @@ -422,10 +426,8 @@ extern int lvbe_obj_set_style_pad_right(bvm *vm); extern int lvbe_obj_set_style_pad_row(bvm *vm); extern int lvbe_obj_set_style_pad_column(bvm *vm); extern int lvbe_obj_set_style_bg_color(bvm *vm); -extern int lvbe_obj_set_style_bg_color_filtered(bvm *vm); extern int lvbe_obj_set_style_bg_opa(bvm *vm); extern int lvbe_obj_set_style_bg_grad_color(bvm *vm); -extern int lvbe_obj_set_style_bg_grad_color_filtered(bvm *vm); extern int lvbe_obj_set_style_bg_grad_dir(bvm *vm); extern int lvbe_obj_set_style_bg_main_stop(bvm *vm); extern int lvbe_obj_set_style_bg_grad_stop(bvm *vm); @@ -434,18 +436,15 @@ extern int lvbe_obj_set_style_bg_dither_mode(bvm *vm); extern int lvbe_obj_set_style_bg_img_src(bvm *vm); extern int lvbe_obj_set_style_bg_img_opa(bvm *vm); extern int lvbe_obj_set_style_bg_img_recolor(bvm *vm); -extern int lvbe_obj_set_style_bg_img_recolor_filtered(bvm *vm); extern int lvbe_obj_set_style_bg_img_recolor_opa(bvm *vm); extern int lvbe_obj_set_style_bg_img_tiled(bvm *vm); extern int lvbe_obj_set_style_border_color(bvm *vm); -extern int lvbe_obj_set_style_border_color_filtered(bvm *vm); extern int lvbe_obj_set_style_border_opa(bvm *vm); extern int lvbe_obj_set_style_border_width(bvm *vm); extern int lvbe_obj_set_style_border_side(bvm *vm); extern int lvbe_obj_set_style_border_post(bvm *vm); extern int lvbe_obj_set_style_outline_width(bvm *vm); extern int lvbe_obj_set_style_outline_color(bvm *vm); -extern int lvbe_obj_set_style_outline_color_filtered(bvm *vm); extern int lvbe_obj_set_style_outline_opa(bvm *vm); extern int lvbe_obj_set_style_outline_pad(bvm *vm); extern int lvbe_obj_set_style_shadow_width(bvm *vm); @@ -453,27 +452,22 @@ extern int lvbe_obj_set_style_shadow_ofs_x(bvm *vm); extern int lvbe_obj_set_style_shadow_ofs_y(bvm *vm); extern int lvbe_obj_set_style_shadow_spread(bvm *vm); extern int lvbe_obj_set_style_shadow_color(bvm *vm); -extern int lvbe_obj_set_style_shadow_color_filtered(bvm *vm); extern int lvbe_obj_set_style_shadow_opa(bvm *vm); extern int lvbe_obj_set_style_img_opa(bvm *vm); extern int lvbe_obj_set_style_img_recolor(bvm *vm); -extern int lvbe_obj_set_style_img_recolor_filtered(bvm *vm); extern int lvbe_obj_set_style_img_recolor_opa(bvm *vm); extern int lvbe_obj_set_style_line_width(bvm *vm); extern int lvbe_obj_set_style_line_dash_width(bvm *vm); extern int lvbe_obj_set_style_line_dash_gap(bvm *vm); extern int lvbe_obj_set_style_line_rounded(bvm *vm); extern int lvbe_obj_set_style_line_color(bvm *vm); -extern int lvbe_obj_set_style_line_color_filtered(bvm *vm); extern int lvbe_obj_set_style_line_opa(bvm *vm); extern int lvbe_obj_set_style_arc_width(bvm *vm); extern int lvbe_obj_set_style_arc_rounded(bvm *vm); extern int lvbe_obj_set_style_arc_color(bvm *vm); -extern int lvbe_obj_set_style_arc_color_filtered(bvm *vm); extern int lvbe_obj_set_style_arc_opa(bvm *vm); extern int lvbe_obj_set_style_arc_img_src(bvm *vm); extern int lvbe_obj_set_style_text_color(bvm *vm); -extern int lvbe_obj_set_style_text_color_filtered(bvm *vm); extern int lvbe_obj_set_style_text_opa(bvm *vm); extern int lvbe_obj_set_style_text_font(bvm *vm); extern int lvbe_obj_set_style_text_letter_space(bvm *vm); @@ -485,6 +479,7 @@ extern int lvbe_obj_set_style_clip_corner(bvm *vm); extern int lvbe_obj_set_style_opa(bvm *vm); extern int lvbe_obj_set_style_color_filter_dsc(bvm *vm); extern int lvbe_obj_set_style_color_filter_opa(bvm *vm); +extern int lvbe_obj_set_style_anim(bvm *vm); extern int lvbe_obj_set_style_anim_time(bvm *vm); extern int lvbe_obj_set_style_anim_speed(bvm *vm); extern int lvbe_obj_set_style_transition(bvm *vm); @@ -559,11 +554,13 @@ extern int lvbe_group_focus_prev(bvm *vm); extern int lvbe_group_focus_freeze(bvm *vm); extern int lvbe_group_send_data(bvm *vm); extern int lvbe_group_set_focus_cb(bvm *vm); +extern int lvbe_group_set_edge_cb(bvm *vm); extern int lvbe_group_set_refocus_policy(bvm *vm); extern int lvbe_group_set_editing(bvm *vm); extern int lvbe_group_set_wrap(bvm *vm); extern int lvbe_group_get_focused(bvm *vm); extern int lvbe_group_get_focus_cb(bvm *vm); +extern int lvbe_group_get_edge_cb(bvm *vm); extern int lvbe_group_get_editing(bvm *vm); extern int lvbe_group_get_wrap(bvm *vm); extern int lvbe_group_get_obj_count(bvm *vm); @@ -686,7 +683,7 @@ extern int lvbe_spinbox_set_rollover(bvm *vm); extern int lvbe_spinbox_set_digit_format(bvm *vm); extern int lvbe_spinbox_set_step(bvm *vm); extern int lvbe_spinbox_set_range(bvm *vm); -extern int lvbe_spinbox_set_pos(bvm *vm); +extern int lvbe_spinbox_set_cursor_pos(bvm *vm); extern int lvbe_spinbox_set_digit_step_direction(bvm *vm); extern int lvbe_spinbox_get_rollover(bvm *vm); extern int lvbe_spinbox_get_value(bvm *vm); @@ -711,6 +708,7 @@ extern int lvbe_anim_set_path_cb(bvm *vm); extern int lvbe_anim_set_start_cb(bvm *vm); extern int lvbe_anim_set_get_value_cb(bvm *vm); extern int lvbe_anim_set_ready_cb(bvm *vm); +extern int lvbe_anim_set_deleted_cb(bvm *vm); extern int lvbe_anim_set_playback_time(bvm *vm); extern int lvbe_anim_set_playback_delay(bvm *vm); extern int lvbe_anim_set_repeat_count(bvm *vm); @@ -756,6 +754,8 @@ extern int lvbe_arc_get_value(bvm *vm); extern int lvbe_arc_get_min_value(bvm *vm); extern int lvbe_arc_get_max_value(bvm *vm); extern int lvbe_arc_get_mode(bvm *vm); +extern int lvbe_arc_align_obj_to_angle(bvm *vm); +extern int lvbe_arc_rotate_obj_to_angle(bvm *vm); /* `lv_bar` external functions definitions */ extern int lvbe_bar_create(bvm *vm); @@ -833,6 +833,7 @@ extern int lvbe_dropdown_get_options(bvm *vm); extern int lvbe_dropdown_get_selected(bvm *vm); extern int lvbe_dropdown_get_option_cnt(bvm *vm); extern int lvbe_dropdown_get_selected_str(bvm *vm); +extern int lvbe_dropdown_get_option_index(bvm *vm); extern int lvbe_dropdown_get_symbol(bvm *vm); extern int lvbe_dropdown_get_selected_highlight(bvm *vm); extern int lvbe_dropdown_get_dir(bvm *vm); @@ -919,6 +920,7 @@ extern int lvbe_textarea_set_placeholder_text(bvm *vm); extern int lvbe_textarea_set_cursor_pos(bvm *vm); extern int lvbe_textarea_set_cursor_click_pos(bvm *vm); extern int lvbe_textarea_set_password_mode(bvm *vm); +extern int lvbe_textarea_set_password_bullet(bvm *vm); extern int lvbe_textarea_set_one_line(bvm *vm); extern int lvbe_textarea_set_accepted_chars(bvm *vm); extern int lvbe_textarea_set_max_length(bvm *vm); @@ -932,6 +934,7 @@ extern int lvbe_textarea_get_label(bvm *vm); extern int lvbe_textarea_get_cursor_pos(bvm *vm); extern int lvbe_textarea_get_cursor_click_pos(bvm *vm); extern int lvbe_textarea_get_password_mode(bvm *vm); +extern int lvbe_textarea_get_password_bullet(bvm *vm); extern int lvbe_textarea_get_one_line(bvm *vm); extern int lvbe_textarea_get_accepted_chars(bvm *vm); extern int lvbe_textarea_get_max_length(bvm *vm); diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h index 8e216a122..c5d2bbb5f 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h @@ -124,7 +124,13 @@ LV_SCR_LOAD_ANIM_MOVE_LEFT LV_SCR_LOAD_ANIM_MOVE_RIGHT LV_SCR_LOAD_ANIM_MOVE_TOP LV_SCR_LOAD_ANIM_MOVE_BOTTOM +LV_SCR_LOAD_ANIM_FADE_IN LV_SCR_LOAD_ANIM_FADE_ON +LV_SCR_LOAD_ANIM_FADE_OUT +LV_SCR_LOAD_ANIM_OUT_LEFT +LV_SCR_LOAD_ANIM_OUT_RIGHT +LV_SCR_LOAD_ANIM_OUT_TOP +LV_SCR_LOAD_ANIM_OUT_BOTTOM // File: ../../lvgl/src/core/lv_event.h LV_EVENT_ALL @@ -267,6 +273,10 @@ LV_COVER_RES_COVER LV_COVER_RES_NOT_COVER LV_COVER_RES_MASKED +LV_LAYER_TYPE_NONE +LV_LAYER_TYPE_SIMPLE +LV_LAYER_TYPE_TRANSFORM + // File: ../../lvgl/src/core/lv_obj_pos.h // File: ../../lvgl/src/core/lv_obj_scroll.h LV_SCROLLBAR_MODE_OFF @@ -292,6 +302,11 @@ LV_OBJ_TREE_WALK_END // File: ../../lvgl/src/draw/lv_draw_arc.h // File: ../../lvgl/src/draw/lv_draw_img.h // File: ../../lvgl/src/draw/lv_draw_label.h +// File: ../../lvgl/src/draw/lv_draw_layer.h +LV_DRAW_LAYER_FLAG_NONE +LV_DRAW_LAYER_FLAG_HAS_ALPHA +LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE + // File: ../../lvgl/src/draw/lv_draw_line.h // File: ../../lvgl/src/draw/lv_draw_mask.h LV_DRAW_MASK_RES_TRANSP @@ -312,6 +327,7 @@ LV_DRAW_MASK_LINE_SIDE_BOTTOM // File: ../../lvgl/src/draw/lv_draw_rect.h LV_RADIUS_CIRCLE +// File: ../../lvgl/src/draw/lv_draw_transform.h // File: ../../lvgl/src/draw/lv_draw_triangle.h // File: ../../lvgl/src/draw/lv_img_buf.h LV_IMG_CF_UNKNOWN @@ -329,6 +345,12 @@ LV_IMG_CF_ALPHA_1BIT LV_IMG_CF_ALPHA_2BIT LV_IMG_CF_ALPHA_4BIT LV_IMG_CF_ALPHA_8BIT +LV_IMG_CF_RGB888 +LV_IMG_CF_RGBA8888 +LV_IMG_CF_RGBX8888 +LV_IMG_CF_RGB565 +LV_IMG_CF_RGBA5658 +LV_IMG_CF_RGB565A8 // File: ../../lvgl/src/draw/lv_img_cache.h // File: ../../lvgl/src/draw/lv_img_decoder.h @@ -623,23 +645,19 @@ LV_STYLE_MAX_HEIGHT LV_STYLE_X LV_STYLE_Y LV_STYLE_ALIGN -LV_STYLE_TRANSFORM_WIDTH -LV_STYLE_TRANSFORM_HEIGHT -LV_STYLE_TRANSLATE_X -LV_STYLE_TRANSLATE_Y -LV_STYLE_TRANSFORM_ZOOM -LV_STYLE_TRANSFORM_ANGLE +LV_STYLE_LAYOUT +LV_STYLE_RADIUS LV_STYLE_PAD_TOP LV_STYLE_PAD_BOTTOM LV_STYLE_PAD_LEFT LV_STYLE_PAD_RIGHT LV_STYLE_PAD_ROW LV_STYLE_PAD_COLUMN +LV_STYLE_BASE_DIR +LV_STYLE_CLIP_CORNER LV_STYLE_BG_COLOR -LV_STYLE_BG_COLOR_FILTERED LV_STYLE_BG_OPA LV_STYLE_BG_GRAD_COLOR -LV_STYLE_BG_GRAD_COLOR_FILTERED LV_STYLE_BG_GRAD_DIR LV_STYLE_BG_MAIN_STOP LV_STYLE_BG_GRAD_STOP @@ -648,18 +666,15 @@ LV_STYLE_BG_DITHER_MODE LV_STYLE_BG_IMG_SRC LV_STYLE_BG_IMG_OPA LV_STYLE_BG_IMG_RECOLOR -LV_STYLE_BG_IMG_RECOLOR_FILTERED LV_STYLE_BG_IMG_RECOLOR_OPA LV_STYLE_BG_IMG_TILED LV_STYLE_BORDER_COLOR -LV_STYLE_BORDER_COLOR_FILTERED LV_STYLE_BORDER_OPA LV_STYLE_BORDER_WIDTH LV_STYLE_BORDER_SIDE LV_STYLE_BORDER_POST LV_STYLE_OUTLINE_WIDTH LV_STYLE_OUTLINE_COLOR -LV_STYLE_OUTLINE_COLOR_FILTERED LV_STYLE_OUTLINE_OPA LV_STYLE_OUTLINE_PAD LV_STYLE_SHADOW_WIDTH @@ -667,45 +682,48 @@ LV_STYLE_SHADOW_OFS_X LV_STYLE_SHADOW_OFS_Y LV_STYLE_SHADOW_SPREAD LV_STYLE_SHADOW_COLOR -LV_STYLE_SHADOW_COLOR_FILTERED LV_STYLE_SHADOW_OPA LV_STYLE_IMG_OPA LV_STYLE_IMG_RECOLOR -LV_STYLE_IMG_RECOLOR_FILTERED LV_STYLE_IMG_RECOLOR_OPA LV_STYLE_LINE_WIDTH LV_STYLE_LINE_DASH_WIDTH LV_STYLE_LINE_DASH_GAP LV_STYLE_LINE_ROUNDED LV_STYLE_LINE_COLOR -LV_STYLE_LINE_COLOR_FILTERED LV_STYLE_LINE_OPA LV_STYLE_ARC_WIDTH LV_STYLE_ARC_ROUNDED LV_STYLE_ARC_COLOR -LV_STYLE_ARC_COLOR_FILTERED LV_STYLE_ARC_OPA LV_STYLE_ARC_IMG_SRC LV_STYLE_TEXT_COLOR -LV_STYLE_TEXT_COLOR_FILTERED LV_STYLE_TEXT_OPA LV_STYLE_TEXT_FONT LV_STYLE_TEXT_LETTER_SPACE LV_STYLE_TEXT_LINE_SPACE LV_STYLE_TEXT_DECOR LV_STYLE_TEXT_ALIGN -LV_STYLE_RADIUS -LV_STYLE_CLIP_CORNER LV_STYLE_OPA LV_STYLE_COLOR_FILTER_DSC LV_STYLE_COLOR_FILTER_OPA +LV_STYLE_ANIM LV_STYLE_ANIM_TIME LV_STYLE_ANIM_SPEED LV_STYLE_TRANSITION LV_STYLE_BLEND_MODE -LV_STYLE_LAYOUT -LV_STYLE_BASE_DIR +LV_STYLE_TRANSFORM_WIDTH +LV_STYLE_TRANSFORM_HEIGHT +LV_STYLE_TRANSLATE_X +LV_STYLE_TRANSLATE_Y +LV_STYLE_TRANSFORM_ZOOM +LV_STYLE_TRANSFORM_ANGLE +LV_STYLE_TRANSFORM_PIVOT_X +LV_STYLE_TRANSFORM_PIVOT_Y LV_STYLE_PROP_ANY +LV_STYLE_RES_NOT_FOUND +LV_STYLE_RES_FOUND +LV_STYLE_RES_INHERIT LV_IMG_ZOOM_NONE // File: ../../lvgl/src/misc/lv_style_gen.h // File: ../../lvgl/src/misc/lv_templ.h diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index 46c91aa8f..125384800 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -44,6 +44,8 @@ void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t tim uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) void lv_disp_trig_activity(lv_disp_t * disp) void lv_disp_clean_dcache(lv_disp_t * disp) +void lv_disp_enable_invalidation(lv_disp_t * disp, bool en) +bool lv_disp_is_invalidation_enabled(lv_disp_t * disp) static inline lv_obj_t * lv_scr_act(void) static inline lv_obj_t * lv_layer_top(void) static inline lv_obj_t * lv_layer_sys(void) @@ -80,11 +82,13 @@ void lv_group_focus_prev(lv_group_t * group) void lv_group_focus_freeze(lv_group_t * group, bool en) lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) +void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb) void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy) void lv_group_set_editing(lv_group_t * group, bool edit) void lv_group_set_wrap(lv_group_t * group, bool en) struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group) lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group) +lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group) bool lv_group_get_editing(const lv_group_t * group) bool lv_group_get_wrap(lv_group_t * group) uint32_t lv_group_get_obj_count(lv_group_t * group) @@ -187,6 +191,8 @@ bool lv_obj_refresh_self_size(struct _lv_obj_t * obj) void lv_obj_refr_pos(struct _lv_obj_t * obj) void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating) +void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv) +void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv) void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area) void lv_obj_invalidate(const struct _lv_obj_t * obj) bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area) @@ -235,7 +241,8 @@ void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_ void lv_obj_enable_style_refresh(bool en) lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) -lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) +void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, lv_style_selector_t selector) +lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector) void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay) void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay) @@ -264,6 +271,8 @@ static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * o static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part) static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part) @@ -334,6 +343,7 @@ static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, ui static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part) static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part) static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part) static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part) static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part) static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part) @@ -355,6 +365,8 @@ void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_s void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -362,10 +374,8 @@ void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_sty void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -374,18 +384,15 @@ void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t va void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector) void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -393,27 +400,22 @@ void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_ void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector) void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) @@ -425,6 +427,7 @@ void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_s void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) @@ -451,7 +454,7 @@ void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, vo // ../../lvgl/src/core/lv_refr.h void lv_refr_now(lv_disp_t * disp) -void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) // ../../lvgl/src/core/lv_theme.h lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) @@ -466,6 +469,7 @@ lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj) // ../../lvgl/src/draw/lv_draw.h void lv_draw_init(void) +void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx) // ../../lvgl/src/draw/lv_draw_arc.h void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc) @@ -483,6 +487,12 @@ void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) void lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint) void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, uint32_t letter) +// ../../lvgl/src/draw/lv_draw_layer.h +struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, lv_draw_layer_flags_t flags) +void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, lv_draw_layer_flags_t flags) +void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, lv_draw_img_dsc_t * draw_dsc) +void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx) + // ../../lvgl/src/draw/lv_draw_line.h void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, const lv_point_t * point2) @@ -510,6 +520,9 @@ void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_po void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +// ../../lvgl/src/draw/lv_draw_transform.h +void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) + // ../../lvgl/src/draw/lv_draw_triangle.h void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], uint16_t point_cnt) void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]) @@ -592,6 +605,7 @@ bool lv_theme_default_is_inited(void) // ../../lvgl/src/extra/themes/mono/lv_theme_mono.h lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) +bool lv_theme_mono_is_inited(void) // ../../lvgl/src/extra/widgets/chart/lv_chart.h lv_obj_t * lv_chart_create(lv_obj_t * parent) @@ -689,7 +703,7 @@ void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position) void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) -void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos) +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos) void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) bool lv_spinbox_get_rollover(lv_obj_t * obj) int32_t lv_spinbox_get_value(lv_obj_t * obj) @@ -726,6 +740,7 @@ static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb) static inline void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_t get_value_cb) static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb) +static inline void lv_anim_set_deleted_cb(lv_anim_t * a, lv_anim_deleted_cb_t deleted_cb) static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) @@ -739,6 +754,7 @@ static inline void * lv_anim_get_user_data(lv_anim_t * a) bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) void lv_anim_del_all(void) lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) +struct _lv_timer_t * lv_anim_get_timer(void) static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) uint16_t lv_anim_count_running(void) @@ -756,6 +772,7 @@ uint32_t lv_area_get_size(const lv_area_t * area_p) void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra) void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs) void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y) +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot) static inline lv_coord_t lv_pct(lv_coord_t x) // ../../lvgl/src/misc/lv_color.h @@ -798,19 +815,22 @@ uint32_t lv_rand(uint32_t min, uint32_t max) // ../../lvgl/src/misc/lv_style.h void lv_style_init(lv_style_t * style) void lv_style_reset(lv_style_t * style) -lv_style_prop_t lv_style_register_prop(void) +lv_style_prop_t lv_style_register_prop(uint8_t flag) +lv_style_prop_t lv_style_get_num_custom_props(void) bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value) -lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) -static inline lv_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) +void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta) +lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) +static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) bool lv_style_is_empty(const lv_style_t * style) static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) +static inline bool lv_style_prop_has_flag(lv_style_prop_t prop, uint8_t flag) // ../../lvgl/src/misc/lv_style_gen.h void lv_style_set_width(lv_style_t * style, lv_coord_t value) @@ -828,6 +848,8 @@ void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value) void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value) void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value) void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value) +void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value) +void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value) void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value) void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value) void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value) @@ -835,10 +857,8 @@ void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value) void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value) void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value) void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_grad_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value) void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value) @@ -847,18 +867,15 @@ void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value) void lv_style_set_bg_img_src(lv_style_t * style, const void * value) void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_img_recolor_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_bg_img_tiled(lv_style_t * style, bool value) void lv_style_set_border_color(lv_style_t * style, lv_color_t value) -void lv_style_set_border_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_border_width(lv_style_t * style, lv_coord_t value) void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value) void lv_style_set_border_post(lv_style_t * style, bool value) void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value) void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) -void lv_style_set_outline_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value) void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value) @@ -866,27 +883,22 @@ void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value) void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value) void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value) void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) -void lv_style_set_shadow_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value) -void lv_style_set_img_recolor_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_line_width(lv_style_t * style, lv_coord_t value) void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value) void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) void lv_style_set_line_rounded(lv_style_t * style, bool value) void lv_style_set_line_color(lv_style_t * style, lv_color_t value) -void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) void lv_style_set_arc_rounded(lv_style_t * style, bool value) void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) -void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_arc_img_src(lv_style_t * style, const void * value) void lv_style_set_text_color(lv_style_t * style, lv_color_t value) -void lv_style_set_text_color_filtered(lv_style_t * style, lv_color_t value) void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value) void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value) @@ -898,6 +910,7 @@ void lv_style_set_clip_corner(lv_style_t * style, bool value) void lv_style_set_opa(lv_style_t * style, lv_opa_t value) void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value) void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) void lv_style_set_anim_time(lv_style_t * style, uint32_t value) void lv_style_set_anim_speed(lv_style_t * style, uint32_t value) void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value) @@ -907,6 +920,7 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) // ../../lvgl/src/misc/lv_timer.h uint32_t lv_timer_handler(void) +static inline uint32_t lv_timer_handler_run_in_period(uint32_t ms) lv_timer_t * lv_timer_create_basic(void) lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data) void lv_timer_del(lv_timer_t * timer) @@ -923,17 +937,17 @@ lv_timer_t * lv_timer_get_next(lv_timer_t * timer) // ../../lvgl/src/widgets/lv_arc.h lv_obj_t * lv_arc_create(lv_obj_t * parent) -void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start) -void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end) -void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end) -void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start) -void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end) -void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end) -void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation) -void lv_arc_set_mode(lv_obj_t * arc, lv_arc_mode_t type) -void lv_arc_set_value(lv_obj_t * arc, int16_t value) -void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max) -void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate) +void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) +void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) +void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) +void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) +void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation) +void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) +void lv_arc_set_value(lv_obj_t * obj, int16_t value) +void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) +void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) uint16_t lv_arc_get_angle_start(lv_obj_t * obj) uint16_t lv_arc_get_angle_end(lv_obj_t * obj) uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj) @@ -942,6 +956,8 @@ int16_t lv_arc_get_value(const lv_obj_t * obj) int16_t lv_arc_get_min_value(const lv_obj_t * obj) int16_t lv_arc_get_max_value(const lv_obj_t * obj) lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset) +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset) // ../../lvgl/src/widgets/lv_bar.h lv_obj_t * lv_bar_create(lv_obj_t * parent) @@ -1019,6 +1035,7 @@ const char * lv_dropdown_get_options(const lv_obj_t * obj) uint16_t lv_dropdown_get_selected(const lv_obj_t * obj) uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj) void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size) +int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option) const char * lv_dropdown_get_symbol(lv_obj_t * obj) bool lv_dropdown_get_selected_highlight(lv_obj_t * obj) lv_dir_t lv_dropdown_get_dir(const lv_obj_t * obj) @@ -1126,6 +1143,7 @@ void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en) void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) +void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet) void lv_textarea_set_one_line(lv_obj_t * obj, bool en) void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list) void lv_textarea_set_max_length(lv_obj_t * obj, uint32_t num) @@ -1139,6 +1157,7 @@ lv_obj_t * lv_textarea_get_label(const lv_obj_t * obj) uint32_t lv_textarea_get_cursor_pos(const lv_obj_t * obj) bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj) bool lv_textarea_get_password_mode(const lv_obj_t * obj) +const char * lv_textarea_get_password_bullet(lv_obj_t * obj) bool lv_textarea_get_one_line(const lv_obj_t * obj) const char * lv_textarea_get_accepted_chars(lv_obj_t * obj) uint32_t lv_textarea_get_max_length(lv_obj_t * obj) diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c b/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c index 62b092dd8..33004e1e0 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c +++ b/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c @@ -138,7 +138,7 @@ const be_ctypes_structure_t be_lv_draw_img_dsc = { 10, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[10]) { - { "angle", 0, 0, 0, ctypes_u16, 0 }, + { "angle", 0, 0, 0, ctypes_i16, 0 }, { "antialias", 20, 0, 1, ctypes_bf, 0 }, { "blend_mode", 12, 0, 4, ctypes_bf, 0 }, { "frame_id", 16, 0, 0, ctypes_i32, 0 }, @@ -175,6 +175,27 @@ const be_ctypes_structure_t be_lv_obj_draw_part_dsc = { { "value", 64, 0, 0, ctypes_i32, 0 }, }}; +const be_ctypes_structure_t be_lv_draw_layer_ctx = { + 40, /* size in bytes */ + 14, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[14]) { + { "area_act_x1", 8, 0, 0, ctypes_i16, 0 }, + { "area_act_x2", 12, 0, 0, ctypes_i16, 0 }, + { "area_act_y1", 10, 0, 0, ctypes_i16, 0 }, + { "area_act_y2", 14, 0, 0, ctypes_i16, 0 }, + { "area_full_x1", 0, 0, 0, ctypes_i16, 0 }, + { "area_full_x2", 4, 0, 0, ctypes_i16, 0 }, + { "area_full_y1", 2, 0, 0, ctypes_i16, 0 }, + { "area_full_y2", 6, 0, 0, ctypes_i16, 0 }, + { "buf", 32, 0, 0, ctypes_ptr32, 0 }, + { "buf_area", 28, 0, 0, ctypes_ptr32, 0 }, + { "clip_area", 24, 0, 0, ctypes_ptr32, 0 }, + { "max_row_with_alpha", 16, 0, 0, ctypes_i16, 0 }, + { "max_row_with_no_alpha", 18, 0, 0, ctypes_i16, 0 }, + { "screen_transp", 36, 0, 0, ctypes_u8, 0 }, +}}; + const be_ctypes_structure_t be_lv_draw_mask_common_dsc = { 8, /* size in bytes */ 2, /* number of elements */ @@ -446,68 +467,6 @@ const be_ctypes_structure_t be_lv_meter_indicator = { { "type", 4, 0, 0, ctypes_u8, 0 }, }}; -const be_ctypes_structure_t be_lv_meter_indicator_needle_img = { - 24, /* size in bytes */ - 8, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[8]) { - { "end_value", 12, 0, 0, ctypes_i32, 0 }, - { "opa", 5, 0, 0, ctypes_u8, 0 }, - { "pivot_x", 20, 0, 0, ctypes_i16, 0 }, - { "pivot_y", 22, 0, 0, ctypes_i16, 0 }, - { "scale", 0, 0, 0, ctypes_ptr32, 0 }, - { "src", 16, 0, 0, ctypes_ptr32, 0 }, - { "start_value", 8, 0, 0, ctypes_i32, 0 }, - { "type", 4, 0, 0, ctypes_u8, 0 }, -}}; - -const be_ctypes_structure_t be_lv_meter_indicator_needle_line = { - 24, /* size in bytes */ - 8, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[8]) { - { "color", 20, 0, 0, ctypes_u16, 1 }, - { "end_value", 12, 0, 0, ctypes_i32, 0 }, - { "opa", 5, 0, 0, ctypes_u8, 0 }, - { "r_mod", 18, 0, 0, ctypes_i16, 0 }, - { "scale", 0, 0, 0, ctypes_ptr32, 0 }, - { "start_value", 8, 0, 0, ctypes_i32, 0 }, - { "type", 4, 0, 0, ctypes_u8, 0 }, - { "width", 16, 0, 0, ctypes_u16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_meter_indicator_arc = { - 28, /* size in bytes */ - 9, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[9]) { - { "color", 24, 0, 0, ctypes_u16, 1 }, - { "end_value", 12, 0, 0, ctypes_i32, 0 }, - { "opa", 5, 0, 0, ctypes_u8, 0 }, - { "r_mod", 26, 0, 0, ctypes_i16, 0 }, - { "scale", 0, 0, 0, ctypes_ptr32, 0 }, - { "src", 20, 0, 0, ctypes_ptr32, 0 }, - { "start_value", 8, 0, 0, ctypes_i32, 0 }, - { "type", 4, 0, 0, ctypes_u8, 0 }, - { "width", 16, 0, 0, ctypes_u16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_meter_indicator_scale_lines = { - 24, /* size in bytes */ - 9, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[9]) { - { "color_end", 20, 0, 0, ctypes_u16, 1 }, - { "color_start", 18, 0, 0, ctypes_u16, 1 }, - { "end_value", 12, 0, 0, ctypes_i32, 0 }, - { "local_grad", 22, 0, 1, ctypes_bf, 0 }, - { "opa", 5, 0, 0, ctypes_u8, 0 }, - { "scale", 0, 0, 0, ctypes_ptr32, 0 }, - { "start_value", 8, 0, 0, ctypes_i32, 0 }, - { "type", 4, 0, 0, ctypes_u8, 0 }, - { "width_mod", 16, 0, 0, ctypes_i16, 0 }, -}}; - const be_ctypes_structure_t be_lv_chart_series = { 16, /* size in bytes */ 9, /* number of elements */ @@ -654,29 +613,36 @@ const be_ctypes_structure_t be_lv_timer = { }}; const be_ctypes_structure_t be_lv_draw_ctx = { - 60, /* size in bytes */ - 19, /* number of elements */ + 88, /* size in bytes */ + 26, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[19]) { + (const be_ctypes_structure_item_t[26]) { { "buf", 0, 0, 0, ctypes_ptr32, 0 }, { "buf_area_x1", 4, 0, 0, ctypes_i16, 0 }, { "buf_area_x2", 8, 0, 0, ctypes_i16, 0 }, { "buf_area_y1", 6, 0, 0, ctypes_i16, 0 }, { "buf_area_y2", 10, 0, 0, ctypes_i16, 0 }, + { "buffer_copy", 60, 0, 0, ctypes_ptr32, 0 }, { "clip_area_x1", 12, 0, 0, ctypes_i16, 0 }, { "clip_area_x2", 16, 0, 0, ctypes_i16, 0 }, { "clip_area_y1", 14, 0, 0, ctypes_i16, 0 }, { "clip_area_y2", 18, 0, 0, ctypes_i16, 0 }, { "draw_arc", 24, 0, 0, ctypes_ptr32, 0 }, - { "draw_bg", 48, 0, 0, ctypes_ptr32, 0 }, + { "draw_bg", 52, 0, 0, ctypes_ptr32, 0 }, { "draw_img", 32, 0, 0, ctypes_ptr32, 0 }, { "draw_img_decoded", 28, 0, 0, ctypes_ptr32, 0 }, { "draw_letter", 36, 0, 0, ctypes_ptr32, 0 }, { "draw_line", 40, 0, 0, ctypes_ptr32, 0 }, { "draw_polygon", 44, 0, 0, ctypes_ptr32, 0 }, { "draw_rect", 20, 0, 0, ctypes_ptr32, 0 }, - { "user_data", 56, 0, 0, ctypes_ptr32, 0 }, - { "wait_for_finish", 52, 0, 0, ctypes_ptr32, 0 }, + { "draw_transform", 48, 0, 0, ctypes_ptr32, 0 }, + { "layer_adjust", 68, 0, 0, ctypes_ptr32, 0 }, + { "layer_blend", 72, 0, 0, ctypes_ptr32, 0 }, + { "layer_destroy", 76, 0, 0, ctypes_ptr32, 0 }, + { "layer_init", 64, 0, 0, ctypes_ptr32, 0 }, + { "layer_instance_size", 80, 0, 0, ctypes_u32, 0 }, + { "user_data", 84, 0, 0, ctypes_ptr32, 0 }, + { "wait_for_finish", 56, 0, 0, ctypes_ptr32, 0 }, }}; const be_ctypes_structure_t be_lv_ts_calibration = { @@ -705,6 +671,7 @@ static be_define_ctypes_class(lv_coord, &be_lv_coord, &be_class_ctypes_bytes, "l static be_define_ctypes_class(lv_draw_arc_dsc, &be_lv_draw_arc_dsc, &be_class_ctypes_bytes, "lv_draw_arc_dsc"); static be_define_ctypes_class(lv_draw_ctx, &be_lv_draw_ctx, &be_class_ctypes_bytes, "lv_draw_ctx"); static be_define_ctypes_class(lv_draw_img_dsc, &be_lv_draw_img_dsc, &be_class_ctypes_bytes, "lv_draw_img_dsc"); +static be_define_ctypes_class(lv_draw_layer_ctx, &be_lv_draw_layer_ctx, &be_class_ctypes_bytes, "lv_draw_layer_ctx"); static be_define_ctypes_class(lv_draw_line_dsc, &be_lv_draw_line_dsc, &be_class_ctypes_bytes, "lv_draw_line_dsc"); static be_define_ctypes_class(lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param, &be_class_ctypes_bytes, "lv_draw_mask_angle_param"); static be_define_ctypes_class(lv_draw_mask_angle_param_cfg, &be_lv_draw_mask_angle_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_angle_param_cfg"); @@ -728,10 +695,6 @@ static be_define_ctypes_class(lv_gradient_stop, &be_lv_gradient_stop, &be_class_ static be_define_ctypes_class(lv_img_dsc, &be_lv_img_dsc, &be_class_ctypes_bytes, "lv_img_dsc"); static be_define_ctypes_class(lv_img_header, &be_lv_img_header, &be_class_ctypes_bytes, "lv_img_header"); static be_define_ctypes_class(lv_meter_indicator, &be_lv_meter_indicator, &be_class_ctypes_bytes, "lv_meter_indicator"); -static be_define_ctypes_class(lv_meter_indicator_arc, &be_lv_meter_indicator_arc, &be_class_ctypes_bytes, "lv_meter_indicator_arc"); -static be_define_ctypes_class(lv_meter_indicator_needle_img, &be_lv_meter_indicator_needle_img, &be_class_ctypes_bytes, "lv_meter_indicator_needle_img"); -static be_define_ctypes_class(lv_meter_indicator_needle_line, &be_lv_meter_indicator_needle_line, &be_class_ctypes_bytes, "lv_meter_indicator_needle_line"); -static be_define_ctypes_class(lv_meter_indicator_scale_lines, &be_lv_meter_indicator_scale_lines, &be_class_ctypes_bytes, "lv_meter_indicator_scale_lines"); static be_define_ctypes_class(lv_meter_scale, &be_lv_meter_scale, &be_class_ctypes_bytes, "lv_meter_scale"); static be_define_ctypes_class(lv_obj_class, &be_lv_obj_class, &be_class_ctypes_bytes, "lv_obj_class"); static be_define_ctypes_class(lv_obj_draw_part_dsc, &be_lv_obj_draw_part_dsc, &be_class_ctypes_bytes, "lv_obj_draw_part_dsc"); @@ -751,6 +714,7 @@ void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_draw_arc_dsc); ctypes_register_class(vm, &be_class_lv_draw_ctx); ctypes_register_class(vm, &be_class_lv_draw_img_dsc); + ctypes_register_class(vm, &be_class_lv_draw_layer_ctx); ctypes_register_class(vm, &be_class_lv_draw_line_dsc); ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param); ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param_cfg); @@ -774,10 +738,6 @@ void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_img_dsc); ctypes_register_class(vm, &be_class_lv_img_header); ctypes_register_class(vm, &be_class_lv_meter_indicator); - ctypes_register_class(vm, &be_class_lv_meter_indicator_arc); - ctypes_register_class(vm, &be_class_lv_meter_indicator_needle_img); - ctypes_register_class(vm, &be_class_lv_meter_indicator_needle_line); - ctypes_register_class(vm, &be_class_lv_meter_indicator_scale_lines); ctypes_register_class(vm, &be_class_lv_meter_scale); ctypes_register_class(vm, &be_class_lv_obj_class); ctypes_register_class(vm, &be_class_lv_obj_draw_part_dsc); @@ -798,6 +758,7 @@ be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_draw_arc_dsc", &be_class_lv_draw_arc_dsc }, { "lv_draw_ctx", &be_class_lv_draw_ctx }, { "lv_draw_img_dsc", &be_class_lv_draw_img_dsc }, + { "lv_draw_layer_ctx", &be_class_lv_draw_layer_ctx }, { "lv_draw_line_dsc", &be_class_lv_draw_line_dsc }, { "lv_draw_mask_angle_param", &be_class_lv_draw_mask_angle_param }, { "lv_draw_mask_angle_param_cfg", &be_class_lv_draw_mask_angle_param_cfg }, @@ -821,10 +782,6 @@ be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_img_dsc", &be_class_lv_img_dsc }, { "lv_img_header", &be_class_lv_img_header }, { "lv_meter_indicator", &be_class_lv_meter_indicator }, - { "lv_meter_indicator_arc", &be_class_lv_meter_indicator_arc }, - { "lv_meter_indicator_needle_img", &be_class_lv_meter_indicator_needle_img }, - { "lv_meter_indicator_needle_line", &be_class_lv_meter_indicator_needle_line }, - { "lv_meter_indicator_scale_lines", &be_class_lv_meter_indicator_scale_lines }, { "lv_meter_scale", &be_class_lv_meter_scale }, { "lv_obj_class", &be_class_lv_obj_class }, { "lv_obj_draw_part_dsc", &be_class_lv_obj_draw_part_dsc }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py index e193ece08..14cd55e11 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py +++ b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py @@ -46,18 +46,18 @@ uint32_t = ct.u32 int32_t = ct.i32 ptr = ct.ptr32 -lv_coord = [ # valid LVGL8 +lv_coord = [ # valid LVGL8.3 [lv_coord_t, "v"], ] lv_coord = ct.structure(lv_coord, "lv_coord") -lv_point = [ # valid LVGL8 +lv_point = [ # valid LVGL8.3 [lv_coord_t, "x"], [lv_coord_t, "y"], ] lv_point = ct.structure(lv_point, "lv_point") -lv_area = [ # valid LVGL8 +lv_area = [ # valid LVGL8.3 [lv_coord_t, "x1"], [lv_coord_t, "y1"], [lv_coord_t, "x2"], @@ -67,13 +67,13 @@ lv_area = ct.structure(lv_area, "lv_area") ####################################################################### # lv_grad_dsc -lv_gradient_stop = [ +lv_gradient_stop = [ # valid LVGL8.3 [lv_color, "color"], [uint8_t, "frac"], ] lv_gradient_stop = ct.structure(lv_gradient_stop, "lv_gradient_stop") -lv_grad_dsc = [ +lv_grad_dsc = [ # valid LVGL8.3 [lv_gradient_stop, "stops_0"], [lv_gradient_stop, "stops_1"], [uint8_t, "stops_count"], @@ -82,7 +82,7 @@ lv_grad_dsc = [ ] lv_grad_dsc = ct.structure(lv_grad_dsc, "lv_grad_dsc") -lv_draw_rect_dsc = [ # valid LVGL8.2 +lv_draw_rect_dsc = [ # valid LVGL8.3 [lv_coord_t, "radius"], [lv_blend_mode, "blend_mode"], @@ -122,7 +122,7 @@ lv_draw_rect_dsc = [ # valid LVGL8.2 ] lv_draw_rect_dsc = ct.structure(lv_draw_rect_dsc, "lv_draw_rect_dsc") -lv_draw_line_dsc = [ # valid LVGL8.2 +lv_draw_line_dsc = [ # valid LVGL8.3 [lv_color, "color"], [lv_coord_t, "width"], [lv_coord_t, "dash_width"], @@ -135,7 +135,7 @@ lv_draw_line_dsc = [ # valid LVGL8.2 ] lv_draw_line_dsc = ct.structure(lv_draw_line_dsc, "lv_draw_line_dsc") -lv_draw_arc_dsc = [ # valid LVGL8.2 +lv_draw_arc_dsc = [ # valid LVGL8.3 [lv_color, "color"], [lv_coord_t, "width"], [uint16_t, "start_angle"], @@ -147,8 +147,8 @@ lv_draw_arc_dsc = [ # valid LVGL8.2 ] lv_draw_arc_dsc = ct.structure(lv_draw_arc_dsc, "lv_draw_arc_dsc") -lv_draw_img_dsc = [ # valid LVGL8.2 - [uint16_t, "angle"], +lv_draw_img_dsc = [ # valid LVGL8.3 + [int16_t, "angle"], [uint16_t, "zoom"], [lv_point, "pivot"], @@ -163,7 +163,7 @@ lv_draw_img_dsc = [ # valid LVGL8.2 ] lv_draw_img_dsc = ct.structure(lv_draw_img_dsc, "lv_draw_img_dsc") -lv_obj_draw_part_dsc = [ # valid LVGL8.2 +lv_obj_draw_part_dsc = [ # valid LVGL8.3 [ptr, "draw_ctx"], [ptr, "class_p"], [uint32_t, "type"], @@ -185,18 +185,31 @@ lv_obj_draw_part_dsc = [ # valid LVGL8.2 ] lv_obj_draw_part_dsc = ct.structure(lv_obj_draw_part_dsc, "lv_obj_draw_part_dsc") +lv_draw_layer_ctx = [ # valid LVGL8.3 + [lv_area, "area_full"], + [lv_area, "area_act"], + [lv_coord_t, "max_row_with_alpha"], + [lv_coord_t, "max_row_with_no_alpha"], + [ptr, "buf"], + [ptr, "clip_area"], + [ptr, "buf_area"], + [ptr, "buf"], + [uint8_t, "screen_transp"], +] +lv_draw_layer_ctx = ct.structure(lv_draw_layer_ctx, "lv_draw_layer_ctx") + #- --------- lv_mask --------- -# lv_draw_mask_xcb = ptr # callback lv_draw_mask_type = ct.u8 lv_draw_mask_line_side = ct.u8 -lv_draw_mask_common_dsc = [ # valid LVGL8.2 +lv_draw_mask_common_dsc = [ # valid LVGL8.3 [lv_draw_mask_xcb, "cb"], [lv_draw_mask_type, "type"], ] lv_draw_mask_common_dsc = ct.structure(lv_draw_mask_common_dsc, "lv_draw_mask_common_dsc") -lv_draw_mask_line_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_line_param_cfg = [ # valid LVGL8.3 #/*First point */ [lv_point, "p1"], @@ -208,7 +221,7 @@ lv_draw_mask_line_param_cfg = [ # valid LVGL8.2 ] lv_draw_mask_line_param_cfg = ct.structure(lv_draw_mask_line_param_cfg, "lv_draw_mask_line_param_cfg") -lv_draw_mask_line_param = [ # valid LVGL8.2 +lv_draw_mask_line_param = [ # valid LVGL8.3 #/*The first element must be the common descriptor*/ [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_line_param_cfg, "cfg"], @@ -230,14 +243,14 @@ lv_draw_mask_line_param = [ # valid LVGL8.2 ] lv_draw_mask_line_param = ct.structure(lv_draw_mask_line_param, "lv_draw_mask_line_param") -lv_draw_mask_angle_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_angle_param_cfg = [ # valid LVGL8.3 [lv_point, "vertex_p"], [lv_coord_t, "start_angle"], [lv_coord_t, "end_angle"], ] lv_draw_mask_angle_param_cfg = ct.structure(lv_draw_mask_angle_param_cfg, "lv_draw_mask_angle_param_cfg") -lv_draw_mask_angle_param = [ # valid LVGL8.2 +lv_draw_mask_angle_param = [ # valid LVGL8.3 #/*The first element must be the common descriptor*/ [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_angle_param_cfg, "cfg"], @@ -249,14 +262,14 @@ lv_draw_mask_angle_param = [ # valid LVGL8.2 lv_draw_mask_angle_param = ct.structure(lv_draw_mask_angle_param, "lv_draw_mask_angle_param") -lv_draw_mask_radius_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_radius_param_cfg = [ # valid LVGL8.3 [lv_area, "rect"], [lv_coord_t, "radius"], [uint8_t_1, "outer"], ] lv_draw_mask_radius_param_cfg = ct.structure(lv_draw_mask_radius_param_cfg, "lv_draw_mask_radius_param_cfg") -lv_draw_mask_radius_circle_dsc = [ # valid LVGL8.2 +lv_draw_mask_radius_circle_dsc = [ # valid LVGL8.3 [ptr, "buf"], [ptr, "cir_opa"], [ptr, "x_start_on_y"], @@ -267,7 +280,7 @@ lv_draw_mask_radius_circle_dsc = [ # valid LVGL8.2 ] lv_draw_mask_radius_circle_dsc = ct.structure(lv_draw_mask_radius_circle_dsc, "lv_draw_mask_radius_circle_dsc") -lv_draw_mask_radius_param = [ # valid LVGL8.2 +lv_draw_mask_radius_param = [ # valid LVGL8.3 #/*The first element must be the common descriptor*/ [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_radius_param_cfg, "cfg"], @@ -276,7 +289,7 @@ lv_draw_mask_radius_param = [ # valid LVGL8.2 lv_draw_mask_radius_param = ct.structure(lv_draw_mask_radius_param, "lv_draw_mask_radius_param") -lv_draw_mask_fade_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_fade_param_cfg = [ # valid LVGL8.3 [lv_area, "coords"], [lv_coord_t, "y_top"], [lv_coord_t, "y_bottom"], @@ -285,7 +298,7 @@ lv_draw_mask_fade_param_cfg = [ # valid LVGL8.2 ] lv_draw_mask_fade_param_cfg = ct.structure(lv_draw_mask_fade_param_cfg, "lv_draw_mask_fade_param_cfg") -lv_draw_mask_fade_param = [ # valid LVGL8.2 +lv_draw_mask_fade_param = [ # valid LVGL8.3 # /*The first element must be the common descriptor*/ [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_fade_param_cfg, "cfg"], @@ -293,33 +306,33 @@ lv_draw_mask_fade_param = [ # valid LVGL8.2 lv_draw_mask_fade_param = ct.structure(lv_draw_mask_fade_param, "lv_draw_mask_fade_param") -lv_draw_mask_map_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_map_param_cfg = [ # valid LVGL8.3 [lv_area, "coords"], [ptr, "map"], ] lv_draw_mask_map_param_cfg = ct.structure(lv_draw_mask_map_param_cfg, "lv_draw_mask_map_param_cfg") -lv_draw_mask_map_param = [ # valid LVGL8.2 +lv_draw_mask_map_param = [ # valid LVGL8.3 [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_map_param_cfg, "cfg"], ] lv_draw_mask_map_param = ct.structure(lv_draw_mask_map_param, "lv_draw_mask_map_param") -lv_draw_mask_polygon_param_cfg = [ # valid LVGL8.2 +lv_draw_mask_polygon_param_cfg = [ # valid LVGL8.3 [ptr, "points"], [uint16_t, "point_cnt"], ] lv_draw_mask_polygon_param_cfg = ct.structure(lv_draw_mask_polygon_param_cfg, "lv_draw_mask_polygon_param_cfg") -lv_draw_mask_polygon_param = [ # valid LVGL8.2 +lv_draw_mask_polygon_param = [ # valid LVGL8.3 [lv_draw_mask_common_dsc, "dsc"], [lv_draw_mask_polygon_param_cfg, "cfg"], ] lv_draw_mask_polygon_param = ct.structure(lv_draw_mask_polygon_param, "lv_draw_mask_polygon_param") -lv_draw_mask_saved = [ # valid LVGL8.2 +lv_draw_mask_saved = [ # valid LVGL8.3 [ptr, "param"], [ptr, "custom_id"], ] @@ -328,7 +341,7 @@ lv_draw_mask_saved = ct.structure(lv_draw_mask_saved, "lv_draw_mask_saved") # lv_meter # lv_meter_scale_t -lv_meter_scale = [ # valid LVGL8.2 +lv_meter_scale = [ # valid LVGL8.3 [lv_color, "tick_color"], [uint16_t, "tick_cnt"], [uint16_t, "tick_length"], @@ -351,7 +364,7 @@ lv_meter_scale = [ # valid LVGL8.2 lv_meter_scale = ct.structure(lv_meter_scale, "lv_meter_scale") # lv_meter_indicator_t -lv_meter_indicator = [ # valid LVGL8.2 +lv_meter_indicator = [ # valid LVGL8.3 [ptr, "scale"], [lv_meter_indicator_type_t, "type"], [lv_opa, "opa"], @@ -364,61 +377,61 @@ lv_meter_indicator = [ # valid LVGL8.2 ] lv_meter_indicator = ct.structure(lv_meter_indicator, "lv_meter_indicator") -# variants -lv_meter_indicator_needle_img = [ # valid LVGL8.2 - [ptr, "scale"], - [lv_meter_indicator_type_t, "type"], - [lv_opa, "opa"], - [int32_t, "start_value"], - [int32_t, "end_value"], - # specifc portion - [ptr, "src"], - [lv_point, "pivot"], -] -lv_meter_indicator_needle_img = ct.structure(lv_meter_indicator_needle_img, "lv_meter_indicator_needle_img") +# # variants +# lv_meter_indicator_needle_img = [ # valid LVGL8.2 +# [ptr, "scale"], +# [lv_meter_indicator_type_t, "type"], +# [lv_opa, "opa"], +# [int32_t, "start_value"], +# [int32_t, "end_value"], +# # specifc portion +# [ptr, "src"], +# [lv_point, "pivot"], +# ] +# lv_meter_indicator_needle_img = ct.structure(lv_meter_indicator_needle_img, "lv_meter_indicator_needle_img") -lv_meter_indicator_needle_line = [ # valid LVGL8.2 - [ptr, "scale"], - [lv_meter_indicator_type_t, "type"], - [lv_opa, "opa"], - [int32_t, "start_value"], - [int32_t, "end_value"], - # specifc portion - [uint16_t, "width"], - [int16_t, "r_mod"], - [lv_color, "color"], -] -lv_meter_indicator_needle_line = ct.structure(lv_meter_indicator_needle_line, "lv_meter_indicator_needle_line") +# lv_meter_indicator_needle_line = [ # valid LVGL8.2 +# [ptr, "scale"], +# [lv_meter_indicator_type_t, "type"], +# [lv_opa, "opa"], +# [int32_t, "start_value"], +# [int32_t, "end_value"], +# # specifc portion +# [uint16_t, "width"], +# [int16_t, "r_mod"], +# [lv_color, "color"], +# ] +# lv_meter_indicator_needle_line = ct.structure(lv_meter_indicator_needle_line, "lv_meter_indicator_needle_line") -lv_meter_indicator_arc = [ # valid LVGL8.2 - [ptr, "scale"], - [lv_meter_indicator_type_t, "type"], - [lv_opa, "opa"], - [int32_t, "start_value"], - [int32_t, "end_value"], - # specifc portion - [uint16_t, "width"], - [ptr, "src"], - [lv_color, "color"], - [int16_t, "r_mod"], -] -lv_meter_indicator_arc = ct.structure(lv_meter_indicator_arc, "lv_meter_indicator_arc") +# lv_meter_indicator_arc = [ # valid LVGL8.2 +# [ptr, "scale"], +# [lv_meter_indicator_type_t, "type"], +# [lv_opa, "opa"], +# [int32_t, "start_value"], +# [int32_t, "end_value"], +# # specifc portion +# [uint16_t, "width"], +# [ptr, "src"], +# [lv_color, "color"], +# [int16_t, "r_mod"], +# ] +# lv_meter_indicator_arc = ct.structure(lv_meter_indicator_arc, "lv_meter_indicator_arc") -lv_meter_indicator_scale_lines = [ # valid LVGL8.2 - [ptr, "scale"], - [lv_meter_indicator_type_t, "type"], - [lv_opa, "opa"], - [int32_t, "start_value"], - [int32_t, "end_value"], - # specifc portion - [int16_t, "width_mod"], - [lv_color, "color_start"], - [lv_color, "color_end"], - [uint8_t_1, "local_grad"], -] -lv_meter_indicator_scale_lines = ct.structure(lv_meter_indicator_scale_lines, "lv_meter_indicator_scale_lines") +# lv_meter_indicator_scale_lines = [ # valid LVGL8.2 +# [ptr, "scale"], +# [lv_meter_indicator_type_t, "type"], +# [lv_opa, "opa"], +# [int32_t, "start_value"], +# [int32_t, "end_value"], +# # specifc portion +# [int16_t, "width_mod"], +# [lv_color, "color_start"], +# [lv_color, "color_end"], +# [uint8_t_1, "local_grad"], +# ] +# lv_meter_indicator_scale_lines = ct.structure(lv_meter_indicator_scale_lines, "lv_meter_indicator_scale_lines") -lv_chart_series = [ # valid LVGL8.2 +lv_chart_series = [ # valid LVGL8.3 [ptr, "x_points"], [ptr, "y_points"], [lv_color, "color"], @@ -431,7 +444,7 @@ lv_chart_series = [ # valid LVGL8.2 ] lv_chart_series = ct.structure(lv_chart_series, "lv_chart_series") -lv_chart_cursor = [ # valid LVGL8.2 +lv_chart_cursor = [ # valid LVGL8.3 [lv_point, "pos"], [uint16_t, "point_id"], [lv_color, "color"], @@ -441,7 +454,7 @@ lv_chart_cursor = [ # valid LVGL8.2 ] lv_chart_cursor = ct.structure(lv_chart_cursor, "lv_chart_cursor") -lv_chart_tick_dsc = [ # valid LVGL8.2 +lv_chart_tick_dsc = [ # valid LVGL8.3 [lv_coord_t, "major_len"], [lv_coord_t, "minor_len"], [lv_coord_t, "draw_size"], @@ -461,7 +474,7 @@ destructor_cb = ptr # callback event_cb = ptr # callback lv_event_code = ct.i32 -lv_obj_class = [ # valid LVGL8.2 +lv_obj_class = [ # valid LVGL8.3 [lv_obj_class_ptr, "base_class"], [constructor_cb, "constructor_cb"], [destructor_cb, "destructor_cb"], @@ -475,7 +488,7 @@ lv_obj_class = [ # valid LVGL8.2 ] lv_obj_class = ct.structure(lv_obj_class, "lv_obj_class") -lv_event = [ # valid LVGL8.2 +lv_event = [ # valid LVGL8.3 [lv_obj_ptr, "target"], [lv_obj_ptr, "current_target"], [lv_event_code, "code"], @@ -488,7 +501,7 @@ lv_event = [ # valid LVGL8.2 ] lv_event = ct.structure(lv_event, "lv_event") -lv_sqrt_res = [ # valid LVGL8.2 +lv_sqrt_res = [ # valid LVGL8.3 [uint16_t, "i"], [uint16_t, "f"], ] @@ -496,7 +509,7 @@ lv_sqrt_res = ct.structure(lv_sqrt_res, "lv_sqrt_res") ####################################################################### # lv_img structures -lv_img_header = [ # valid LVGL8.2 +lv_img_header = [ # valid LVGL8.3 [uint8_t_5, "cf"], [uint8_t_3, "always_zero"], [uint8_t_2, "reserved"], @@ -505,7 +518,7 @@ lv_img_header = [ # valid LVGL8.2 ] lv_img_header = ct.structure(lv_img_header, "lv_img_header") -lv_img_dsc = [ # valid LVGL8.2 +lv_img_dsc = [ # valid LVGL8.3 [lv_img_header, "header"], [uint32_t, "data_size"], [ptr, "data"], @@ -514,7 +527,7 @@ lv_img_dsc = ct.structure(lv_img_dsc, "lv_img_dsc") ####################################################################### # lv_style -lv_style_transition_dsc = [ # valid LVGL8.2 +lv_style_transition_dsc = [ # valid LVGL8.3 [ptr, "props"], [ptr, "user_data"], [ptr, "path_xcb"], @@ -532,7 +545,7 @@ lv_style_transition_dsc = ct.structure(lv_style_transition_dsc, "lv_style_transi # ] # lv_color_hsv = ct.structure(lv_color_hsv, "lv_color_hsv") -lv_color_filter_dsc = [ # valid LVGL8.2 +lv_color_filter_dsc = [ # valid LVGL8.3 [ptr, "filter_cb"], [ptr, "user_data"], ] @@ -540,7 +553,7 @@ lv_color_filter_dsc = ct.structure(lv_color_filter_dsc, "lv_color_filter_dsc") ####################################################################### # lv_timer -lv_timer = [ # valid LVGL8.2 +lv_timer = [ # valid LVGL8.3 [uint32_t, "period"], [uint32_t, "last_run"], [ptr, "timer_cb"], @@ -582,7 +595,7 @@ lv_timer = ct.structure(lv_timer, "lv_timer") ####################################################################### # lv_draw_ctx -lv_draw_ctx = [ # valid LVGL8.2 +lv_draw_ctx = [ # valid LVGL8.3 [ptr, "buf"], [lv_area, "buf_area"], [lv_area, "clip_area"], @@ -593,8 +606,15 @@ lv_draw_ctx = [ # valid LVGL8.2 [ptr, "draw_letter"], [ptr, "draw_line"], [ptr, "draw_polygon"], + [ptr, "draw_transform"], [ptr, "draw_bg"], [ptr, "wait_for_finish"], + [ptr, "buffer_copy"], + [ptr, "layer_init"], + [ptr, "layer_adjust"], + [ptr, "layer_blend"], + [ptr, "layer_destroy"], + [uint32_t, "layer_instance_size"], [ptr, "user_data"], ] lv_draw_ctx = ct.structure(lv_draw_ctx, "lv_draw_ctx") @@ -602,7 +622,7 @@ lv_draw_ctx = ct.structure(lv_draw_ctx, "lv_draw_ctx") ####################################################################### # Special structure used to calibrate resistive touchscreens ####################################################################### -lv_ts_calibration = [ # valid LVGL8 +lv_ts_calibration = [ # valid LVGL8.3 [lv_coord_t, "raw_x"], [lv_coord_t, "raw_y"], [lv_coord_t, "x"], diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 8e77aec11..de147382b 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -73,7 +73,7 @@ return_types = { "lv_textarea_style_t": "i", "lv_slider_type_t": "i", "lv_spinner_type_t": "i", - "lv_spinner_dir_t": "i", + "lv_spinner_dir_t": "i", "lv_blend_mode_t": "i", "lv_grad_dir_t": "i", "lv_border_side_t": "i", @@ -107,6 +107,7 @@ return_types = { "lv_style_prop_t": "i", "lv_dither_mode_t": "i", "lv_chart_update_mode_t": "i", + "lv_style_res_t": "i", # layouts "lv_flex_align_t": "i", "lv_flex_flow_t": "i", @@ -157,11 +158,13 @@ return_types = { "lv_style_transition_dsc_t *": "lv_style_transition_dsc", "lv_draw_ctx_t *": "lv_draw_ctx", "_lv_draw_ctx_t *": "lv_draw_ctx", + "_lv_draw_layer_ctx_t *": "lv_draw_layer_ctx", "lv_grad_dsc_t *": "lv_grad_dsc", "lv_sqrt_res_t *": "lv_sqrt_res", # "lv_color_hsv_t *": "lv_color_hsv", "lv_color_filter_dsc_t *": "lv_color_filter_dsc", "lv_timer_t *": "lv_timer", + "_lv_timer_t *": "lv_timer", "lv_coord_t *": "c", # treat as a simple pointer, decoding needs to be done at Berry level "char **": "c", # treat as a simple pointer, decoding needs to be done at Berry level "constchar **": "c", # treat as a simple pointer, decoding needs to be done at Berry level diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/gen.sh b/lib/libesp32_lvgl/lv_binding_berry/tools/gen.sh index 5bd081698..40dcad0c2 100755 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/gen.sh +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/gen.sh @@ -3,4 +3,4 @@ python3 preprocessor.py python3 convert.py cd ../src/embedded -python3 berry_ctypes.py \ No newline at end of file +python3 lvgl_ctypes.py \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/Kconfig b/lib/libesp32_lvgl/lvgl/Kconfig deleted file mode 100644 index 8fe14ec1d..000000000 --- a/lib/libesp32_lvgl/lvgl/Kconfig +++ /dev/null @@ -1,1031 +0,0 @@ -# Kconfig file for LVGL v8.0 - -menu "LVGL configuration" - - # Define CONFIG_LV_CONF_SKIP so we can use LVGL - # without lv_conf.h file, the lv_conf_internal.h and - # lv_conf_kconfig.h files are used instead. - config LV_CONF_SKIP - bool - default y - - config LV_CONF_MINIMAL - bool "LVGL minimal configuration." - - menu "Color settings" - choice LV_COLOR_DEPTH - prompt "Color depth." - default LV_COLOR_DEPTH_16 - help - Color depth to be used. - - config LV_COLOR_DEPTH_32 - bool "32: ARGB8888" - config LV_COLOR_DEPTH_16 - bool "16: RGB565" - config LV_COLOR_DEPTH_8 - bool "8: RGB232" - config LV_COLOR_DEPTH_1 - bool "1: 1 byte per pixel" - endchoice - - config LV_COLOR_DEPTH - int - default 1 if LV_COLOR_DEPTH_1 - default 8 if LV_COLOR_DEPTH_8 - default 16 if LV_COLOR_DEPTH_16 - default 32 if LV_COLOR_DEPTH_32 - - config LV_COLOR_16_SWAP - bool "Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)." - depends on LV_COLOR_DEPTH_16 - - config LV_COLOR_SCREEN_TRANSP - bool "Enable more complex drawing routines to manage screens transparency." - depends on LV_COLOR_DEPTH_32 - help - Can be used if the UI is above another layer, e.g. an OSD menu or video player. - Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to - non LV_OPA_COVER value - - config LV_COLOR_MIX_ROUND_OFS - int "Adjust color mix functions rounding" - default 128 if !LV_COLOR_DEPTH_32 - default 0 if LV_COLOR_DEPTH_32 - range 0 254 - help - 0: no adjustment, get the integer part of the result (round down) - 64: round up from x.75 - 128: round up from half - 192: round up from x.25 - 254: round up - - config LV_COLOR_CHROMA_KEY_HEX - hex "Images pixels with this color will not be drawn (if they are chroma keyed)." - range 0x000000 0xFFFFFF - default 0x00FF00 - help - See misc/lv_color.h for some color values examples. - endmenu - - menu "Memory settings" - config LV_MEM_CUSTOM - bool "If true use custom malloc/free, otherwise use the built-in `lv_mem_alloc()` and `lv_mem_free()`" - - config LV_MEM_SIZE_KILOBYTES - int "Size of the memory used by `lv_mem_alloc` in kilobytes (>= 2kB)" - range 2 128 - default 32 - depends on !LV_MEM_CUSTOM - - config LV_MEM_ADDR - hex "Address for the memory pool instead of allocating it as a normal array" - default 0x0 - depends on !LV_MEM_CUSTOM - - config LV_MEM_CUSTOM_INCLUDE - string "Header to include for the custom memory function" - default "stdlib.h" - depends on LV_MEM_CUSTOM - - config LV_MEM_BUF_MAX_NUM - int "Number of the memory buffer" - default 16 - help - Number of the intermediate memory buffer used during rendering and other - internal processing mechanisms. You will see an error log message if - there wasn't enough buffers. - - config LV_MEMCPY_MEMSET_STD - bool "Use the standard memcpy and memset instead of LVGL's own functions" - endmenu - - menu "HAL Settings" - config LV_DISP_DEF_REFR_PERIOD - int "Default display refresh period (ms)." - default 30 - help - Can be changed in the display driver (`lv_disp_drv_t`). - - config LV_INDEV_DEF_READ_PERIOD - int "Input device read period [ms]." - default 30 - - config LV_TICK_CUSTOM - bool "Use a custom tick source" - - config LV_TICK_CUSTOM_INCLUDE - string "Header for the system time function" - default "Arduino.h" - depends on LV_TICK_CUSTOM - - config LV_DPI_DEF - int "Default Dots Per Inch (in px)." - default 130 - help - Used to initialize default sizes such as widgets sized, style paddings. - (Not so important, you can adjust it to modify default sizes and spaces) - endmenu - - menu "Feature configuration" - - menu "Drawing" - config LV_DRAW_COMPLEX - bool "Enable complex draw engine" - default y - help - Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, - image transformations or any masks. - - config LV_SHADOW_CACHE_SIZE - int "Allow buffering some shadow calculation" - depends on LV_DRAW_COMPLEX - default 0 - help - LV_SHADOW_CACHE_SIZE is the max shadow size to buffer, where - shadow size is `shadow_width + radius`. - Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost. - - config LV_CIRCLE_CACHE_SIZE - int "Set number of maximally cached circle data" - depends on LV_DRAW_COMPLEX - default 4 - help - The circumference of 1/4 circle are saved for anti-aliasing - radius * 4 bytes are used per circle (the most often used - radiuses are saved). - Set to 0 to disable caching. - - config LV_IMG_CACHE_DEF_SIZE - int "Default image cache size. 0 to disable caching." - default 0 - help - If only the built-in image formats are used there is no real advantage of caching. - (I.e. no new image decoder is added). - - With complex image decoders (e.g. PNG or JPG) caching can - save the continuous open/decode of images. - However the opened images might consume additional RAM. - - config LV_GRADIENT_MAX_STOPS - int "Number of stops allowed per gradient." - default 2 - help - Increase this to allow more stops. - This adds (sizeof(lv_color_t) + 1) bytes per additional stop - - config LV_GRAD_CACHE_DEF_SIZE - int "Default gradient buffer size." - default 0 - help - When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. - LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. - If the cache is too small the map will be allocated only while it's required for the drawing. - 0 mean no caching. - - config LV_DITHER_GRADIENT - bool "Allow dithering the gradients" - help - Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) - LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface - The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion - - config LV_DITHER_ERROR_DIFFUSION - bool "Add support for error diffusion dithering" - depends on LV_DITHER_GRADIENT - help - Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. - The increase in memory consumption is (24 bits * object's width) - - config LV_DISP_ROT_MAX_BUF - int "Maximum buffer size to allocate for rotation" - default 10240 - help - Only used if software rotation is enabled in the display driver. - endmenu - - menu "GPU" - config LV_USE_EXTERNAL_RENDERER - bool - - config LV_USE_GPU_STM32_DMA2D - bool "Enable STM32 DMA2D (aka Chrom Art) GPU." - config LV_GPU_DMA2D_CMSIS_INCLUDE - string "include path of CMSIS header of target processor" - depends on LV_USE_GPU_STM32_DMA2D - default "" - help - Must be defined to include path of CMSIS header of target processor - e.g. "stm32f769xx.h" or "stm32f429xx.h" - - config LV_USE_GPU_NXP_PXP - bool "Use NXP's PXP GPU iMX RTxxx platforms." - config LV_USE_GPU_NXP_PXP_AUTO_INIT - bool "Call lv_gpu_nxp_pxp_init() automatically or manually." - depends on LV_USE_GPU_NXP_PXP - help - 1: Add default bare metal and FreeRTOS interrupt handling - routines for PXP (lv_gpu_nxp_pxp_osa.c) and call - lv_gpu_nxp_pxp_init() automatically during lv_init(). - Note that symbol SDK_OS_FREE_RTOS has to be defined in order - to use FreeRTOS OSA, otherwise bare-metal implementation is - selected. - 0: lv_gpu_nxp_pxp_init() has to be called manually before - lv_init(). - - config LV_USE_GPU_NXP_VG_LITE - bool "Use NXP's VG-Lite GPU iMX RTxxx platforms." - - config LV_USE_GPU_SDL - bool "Use SDL renderer API" - select LV_USE_EXTERNAL_RENDERER - default n - config LV_GPU_SDL_INCLUDE_PATH - string "include path of SDL header" - depends on LV_USE_GPU_SDL - default "SDL2/SDL.h" - endmenu - - menu "Logging" - config LV_USE_LOG - bool "Enable the log module" - - choice - bool "Default log verbosity" if LV_USE_LOG - default LV_LOG_LEVEL_WARN - help - Specify how important log should be added. - - config LV_LOG_LEVEL_TRACE - bool "A lot of logs to give detailed information" - config LV_LOG_LEVEL_INFO - bool "Log important events" - config LV_LOG_LEVEL_WARN - bool "Log if something unwanted happened but didn't cause a problem" - config LV_LOG_LEVEL_ERROR - bool "Only critical issues, when the system may fail" - config LV_LOG_LEVEL_USER - bool "Only logs added by the user" - config LV_LOG_LEVEL_NONE - bool "Do not log anything" - endchoice - - config LV_LOG_LEVEL - int - default 0 if LV_LOG_LEVEL_TRACE - default 1 if LV_LOG_LEVEL_INFO - default 2 if LV_LOG_LEVEL_WARN - default 3 if LV_LOG_LEVEL_ERROR - default 4 if LV_LOG_LEVEL_USER - default 5 if LV_LOG_LEVEL_NONE - - config LV_LOG_PRINTF - bool "Print the log with 'printf'" if LV_USE_LOG - help - Use printf for log output. - If not set the user needs to register a callback with `lv_log_register_print_cb`. - - config LV_LOG_TRACE_MEM - bool "Enable/Disable LV_LOG_TRACE in mem module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_TIMER - bool "Enable/Disable LV_LOG_TRACE in timer module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_INDEV - bool "Enable/Disable LV_LOG_TRACE in indev module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_DISP_REFR - bool "Enable/Disable LV_LOG_TRACE in disp refr module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_EVENT - bool "Enable/Disable LV_LOG_TRACE in event module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_OBJ_CREATE - bool "Enable/Disable LV_LOG_TRACE in obj create module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_LAYOUT - bool "Enable/Disable LV_LOG_TRACE in layout module" - default y - depends on LV_USE_LOG - - config LV_LOG_TRACE_ANIM - bool "Enable/Disable LV_LOG_TRACE in anim module" - default y - depends on LV_USE_LOG - endmenu - - menu "Asserts" - config LV_USE_ASSERT_NULL - bool "Check if the parameter is NULL. (Very fast, recommended)" - default y if !LV_CONF_MINIMAL - - config LV_USE_ASSERT_MALLOC - bool "Checks if the memory is successfully allocated or no. (Very fast, recommended)" - default y if !LV_CONF_MINIMAL - - config LV_USE_ASSERT_STYLE - bool "Check if the styles are properly initialized. (Very fast, recommended)" - - config LV_USE_ASSERT_MEM_INTEGRITY - bool "Check the integrity of `lv_mem` after critical operations. (Slow)" - - config LV_USE_ASSERT_OBJ - bool "Check NULL, the object's type and existence (e.g. not deleted). (Slow)." - - config LV_ASSERT_HANDLER_INCLUDE - string "Header to include for the custom assert function" - default "assert.h" - endmenu - - menu "Others" - config LV_USE_PERF_MONITOR - bool "Show CPU usage and FPS count." - - choice - prompt "Performance monitor position." - depends on LV_USE_PERF_MONITOR - default LV_PERF_MONITOR_ALIGN_BOTTOM_RIGHT - - config LV_PERF_MONITOR_ALIGN_TOP_LEFT - bool "Top left" - config LV_PERF_MONITOR_ALIGN_TOP_MID - bool "Top middle" - config LV_PERF_MONITOR_ALIGN_TOP_RIGHT - bool "Top right" - config LV_PERF_MONITOR_ALIGN_BOTTOM_LEFT - bool "Bottom left" - config LV_PERF_MONITOR_ALIGN_BOTTOM_MID - bool "Bottom middle" - config LV_PERF_MONITOR_ALIGN_BOTTOM_RIGHT - bool "Bottom right" - config LV_PERF_MONITOR_ALIGN_LEFT_MID - bool "Left middle" - config LV_PERF_MONITOR_ALIGN_RIGHT_MID - bool "Right middle" - config LV_PERF_MONITOR_ALIGN_BOTTOM_CENTER - bool "Center" - endchoice - - config LV_USE_MEM_MONITOR - bool "Show the used memory and the memory fragmentation." - depends on !LV_MEM_CUSTOM - - choice - prompt "Memory monitor position." - depends on LV_USE_MEM_MONITOR - default LV_MEM_MONITOR_ALIGN_BOTTOM_LEFT - - config LV_MEM_MONITOR_ALIGN_TOP_LEFT - bool "Top left" - config LV_MEM_MONITOR_ALIGN_TOP_MID - bool "Top middle" - config LV_MEM_MONITOR_ALIGN_TOP_RIGHT - bool "Top right" - config LV_MEM_MONITOR_ALIGN_BOTTOM_LEFT - bool "Bottom left" - config LV_MEM_MONITOR_ALIGN_BOTTOM_MID - bool "Bottom middle" - config LV_MEM_MONITOR_ALIGN_BOTTOM_RIGHT - bool "Bottom right" - config LV_MEM_MONITOR_ALIGN_LEFT_MID - bool "Left middle" - config LV_MEM_MONITOR_ALIGN_RIGHT_MID - bool "Right middle" - config LV_MEM_MONITOR_ALIGN_BOTTOM_CENTER - bool "Center" - endchoice - - config LV_USE_REFR_DEBUG - bool "Draw random colored rectangles over the redrawn areas." - - config LV_SPRINTF_CUSTOM - bool "Change the built-in (v)snprintf functions" - - config LV_SPRINTF_INCLUDE - string "Header to include for the custom sprintf function" - depends on LV_SPRINTF_CUSTOM - default "stdio.h" - - config LV_SPRINTF_USE_FLOAT - bool "Enable float in built-in (v)snprintf functions" - depends on !LV_SPRINTF_CUSTOM - - config LV_USE_USER_DATA - bool "Add a 'user_data' to drivers and objects." - default y - - config LV_ENABLE_GC - bool "Enable garbage collector" - - config LV_GC_INCLUDE - string "Header to include for the garbage collector related things" - depends on LV_ENABLE_GC - default "gc.h" - endmenu - - menu "Compiler settings" - config LV_BIG_ENDIAN_SYSTEM - bool "For big endian systems set to 1" - - config LV_ATTRIBUTE_MEM_ALIGN_SIZE - int "Required alignment size for buffers" - default 1 - - config LV_ATTRIBUTE_FAST_MEM_USE_IRAM - bool "Set IRAM as LV_ATTRIBUTE_FAST_MEM" - help - Set this option to configure IRAM as LV_ATTRIBUTE_FAST_MEM - - config LV_USE_LARGE_COORD - bool "Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t" - endmenu - endmenu - - menu "Font usage" - menu "Enable built-in fonts" - config LV_FONT_MONTSERRAT_8 - bool "Enable Montserrat 8" - config LV_FONT_MONTSERRAT_10 - bool "Enable Montserrat 10" - config LV_FONT_MONTSERRAT_12 - bool "Enable Montserrat 12" - config LV_FONT_MONTSERRAT_14 - bool "Enable Montserrat 14" - default y if !LV_CONF_MINIMAL - config LV_FONT_MONTSERRAT_16 - bool "Enable Montserrat 16" - config LV_FONT_MONTSERRAT_18 - bool "Enable Montserrat 18" - config LV_FONT_MONTSERRAT_20 - bool "Enable Montserrat 20" - config LV_FONT_MONTSERRAT_22 - bool "Enable Montserrat 22" - config LV_FONT_MONTSERRAT_24 - bool "Enable Montserrat 24" - config LV_FONT_MONTSERRAT_26 - bool "Enable Montserrat 26" - config LV_FONT_MONTSERRAT_28 - bool "Enable Montserrat 28" - config LV_FONT_MONTSERRAT_30 - bool "Enable Montserrat 30" - config LV_FONT_MONTSERRAT_32 - bool "Enable Montserrat 32" - config LV_FONT_MONTSERRAT_34 - bool "Enable Montserrat 34" - config LV_FONT_MONTSERRAT_36 - bool "Enable Montserrat 36" - config LV_FONT_MONTSERRAT_38 - bool "Enable Montserrat 38" - config LV_FONT_MONTSERRAT_40 - bool "Enable Montserrat 40" - config LV_FONT_MONTSERRAT_42 - bool "Enable Montserrat 42" - config LV_FONT_MONTSERRAT_44 - bool "Enable Montserrat 44" - config LV_FONT_MONTSERRAT_46 - bool "Enable Montserrat 46" - config LV_FONT_MONTSERRAT_48 - bool "Enable Montserrat 48" - - config LV_FONT_MONTSERRAT_12_SUBPX - bool "Enable Montserrat 12 sub-pixel" - config LV_FONT_MONTSERRAT_28_COMPRESSED - bool "Enable Montserrat 28 compressed" - config LV_FONT_DEJAVU_16_PERSIAN_HEBREW - bool "Enable Dejavu 16 Persian, Hebrew, Arabic letters" - config LV_FONT_SIMSUN_16_CJK - bool "Enable Simsun 16 CJK" - - config LV_FONT_UNSCII_8 - bool "Enable UNSCII 8 (Perfect monospace font)" - default y if LV_CONF_MINIMAL - config LV_FONT_UNSCII_16 - bool "Enable UNSCII 16 (Perfect monospace font)" - - config LV_FONT_CUSTOM - bool "Enable the custom font" - config LV_FONT_CUSTOM_DECLARE - string "Header to include for the custom font" - depends on LV_FONT_CUSTOM - endmenu - - choice LV_FONT_DEFAULT - prompt "Select theme default title font" - default LV_FONT_DEFAULT_MONTSERRAT_14 if !LV_CONF_MINIMAL - default LV_FONT_DEFAULT_UNSCII_8 if LV_CONF_MINIMAL - help - Select theme default title font - - config LV_FONT_DEFAULT_MONTSERRAT_8 - bool "Montserrat 8" - select LV_FONT_MONTSERRAT_8 - config LV_FONT_DEFAULT_MONTSERRAT_12 - bool "Montserrat 12" - select LV_FONT_MONTSERRAT_12 - config LV_FONT_DEFAULT_MONTSERRAT_14 - bool "Montserrat 14" - select LV_FONT_MONTSERRAT_14 - config LV_FONT_DEFAULT_MONTSERRAT_16 - bool "Montserrat 16" - select LV_FONT_MONTSERRAT_16 - config LV_FONT_DEFAULT_MONTSERRAT_18 - bool "Montserrat 18" - select LV_FONT_MONTSERRAT_18 - config LV_FONT_DEFAULT_MONTSERRAT_20 - bool "Montserrat 20" - select LV_FONT_MONTSERRAT_20 - config LV_FONT_DEFAULT_MONTSERRAT_22 - bool "Montserrat 22" - select LV_FONT_MONTSERRAT_22 - config LV_FONT_DEFAULT_MONTSERRAT_24 - bool "Montserrat 24" - select LV_FONT_MONTSERRAT_24 - config LV_FONT_DEFAULT_MONTSERRAT_26 - bool "Montserrat 26" - select LV_FONT_MONTSERRAT_26 - config LV_FONT_DEFAULT_MONTSERRAT_28 - bool "Montserrat 28" - select LV_FONT_MONTSERRAT_28 - config LV_FONT_DEFAULT_MONTSERRAT_30 - bool "Montserrat 30" - select LV_FONT_MONTSERRAT_30 - config LV_FONT_DEFAULT_MONTSERRAT_32 - bool "Montserrat 32" - select LV_FONT_MONTSERRAT_32 - config LV_FONT_DEFAULT_MONTSERRAT_34 - bool "Montserrat 34" - select LV_FONT_MONTSERRAT_34 - config LV_FONT_DEFAULT_MONTSERRAT_36 - bool "Montserrat 36" - select LV_FONT_MONTSERRAT_36 - config LV_FONT_DEFAULT_MONTSERRAT_38 - bool "Montserrat 38" - select LV_FONT_MONTSERRAT_38 - config LV_FONT_DEFAULT_MONTSERRAT_40 - bool "Montserrat 40" - select LV_FONT_MONTSERRAT_40 - config LV_FONT_DEFAULT_MONTSERRAT_42 - bool "Montserrat 42" - select LV_FONT_MONTSERRAT_42 - config LV_FONT_DEFAULT_MONTSERRAT_44 - bool "Montserrat 44" - select LV_FONT_MONTSERRAT_44 - config LV_FONT_DEFAULT_MONTSERRAT_46 - bool "Montserrat 46" - select LV_FONT_MONTSERRAT_46 - config LV_FONT_DEFAULT_MONTSERRAT_48 - bool "Montserrat 48" - select LV_FONT_MONTSERRAT_48 - config LV_FONT_DEFAULT_MONTSERRAT_12_SUBPX - bool "Montserrat 12 sub-pixel" - select LV_FONT_MONTSERRAT_12_SUBPX - config LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED - bool "Montserrat 28 compressed" - select LV_FONT_MONTSERRAT_28_COMPRESSED - config LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW - bool "Dejavu 16 Persian, Hebrew, Arabic letters" - select LV_FONT_DEJAVU_16_PERSIAN_HEBREW - config LV_FONT_DEFAULT_SIMSUN_16_CJK - bool "Simsun 16 CJK" - select LV_FONT_SIMSUN_16_CJK - config LV_FONT_DEFAULT_UNSCII_8 - bool "UNSCII 8 (Perfect monospace font)" - select LV_FONT_UNSCII_8 - config LV_FONT_DEFAULT_UNSCII_16 - bool "UNSCII 16 (Perfect monospace font)" - select LV_FONT_UNSCII_16 - endchoice - - config LV_FONT_FMT_TXT_LARGE - bool "Enable it if you have fonts with a lot of characters." - help - The limit depends on the font size, font face and bpp - but with > 10,000 characters if you see issues probably you - need to enable it. - - config LV_USE_FONT_COMPRESSED - bool "Sets support for compressed fonts." - - config LV_USE_FONT_SUBPX - bool "Enable subpixel rendering." - - config LV_FONT_SUBPX_BGR - bool "Use BGR instead RGB for sub-pixel rendering." - depends on LV_USE_FONT_SUBPX - help - Set the pixel order of the display. - Important only if "subpx fonts" are used. - With "normal" font it doesn't matter. - endmenu - - menu "Text Settings" - choice LV_TXT_ENC - prompt "Select a character encoding for strings" - help - Select a character encoding for strings. Your IDE or editor should have the same character encoding. - default LV_TXT_ENC_UTF8 if !LV_CONF_MINIMAL - default LV_TXT_ENC_ASCII if LV_CONF_MINIMAL - - config LV_TXT_ENC_UTF8 - bool "UTF8" - config LV_TXT_ENC_ASCII - bool "ASCII" - endchoice - - config LV_TXT_BREAK_CHARS - string "Can break (wrap) texts on these chars" - default " ,.;:-_" - - config LV_TXT_LINE_BREAK_LONG_LEN - int "Line break long length" - default 0 - help - If a word is at least this long, will break wherever 'prettiest'. - To disable, set to a value <= 0. - - config LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN - int "Min num chars before break" - default 3 - depends on LV_TXT_LINE_BREAK_LONG_LEN > 0 - help - Minimum number of characters in a long word to put on a line before a break. - - config LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN - int "Min num chars after break" - default 3 - depends on LV_TXT_LINE_BREAK_LONG_LEN > 0 - help - Minimum number of characters in a long word to put on a line after a break. - - config LV_TXT_COLOR_CMD - string "The control character to use for signalling text recoloring" - default "#" - - config LV_USE_BIDI - bool "Support bidirectional texts" - help - Allows mixing Left-to-Right and Right-to-Left texts. - The direction will be processed according to the Unicode Bidirectional Algorithm: - https://www.w3.org/International/articles/inline-bidi-markup/uba-basics - - choice - prompt "Set the default BIDI direction" - default LV_BIDI_DIR_AUTO - depends on LV_USE_BIDI - - config LV_BIDI_DIR_LTR - bool "Left-to-Right" - config LV_BIDI_DIR_RTL - bool "Right-to-Left" - config LV_BIDI_DIR_AUTO - bool "Detect texts base direction" - endchoice - - config LV_USE_ARABIC_PERSIAN_CHARS - bool "Enable Arabic/Persian processing" - help - In these languages characters should be replaced with - an other form based on their position in the text. - endmenu - - menu "Widget usage" - config LV_USE_ARC - bool "Arc." - default y if !LV_CONF_MINIMAL - config LV_USE_BAR - bool "Bar." - default y if !LV_CONF_MINIMAL - config LV_USE_BTN - bool "Button." - default y if !LV_CONF_MINIMAL - config LV_USE_BTNMATRIX - bool "Button matrix." - default y if !LV_CONF_MINIMAL - config LV_USE_CANVAS - bool "Canvas. Dependencies: lv_img." - default y if !LV_CONF_MINIMAL - config LV_USE_CHECKBOX - bool "Check Box" - default y if !LV_CONF_MINIMAL - config LV_USE_DROPDOWN - bool "Drop down list. Requires: lv_label." - select LV_USE_LABEL - default y if !LV_CONF_MINIMAL - config LV_USE_IMG - bool "Image. Requires: lv_label." - select LV_USE_LABEL - default y if !LV_CONF_MINIMAL - config LV_USE_LABEL - bool "Label." - default y if !LV_CONF_MINIMAL - config LV_LABEL_TEXT_SELECTION - bool "Enable selecting text of the label." - depends on LV_USE_LABEL - default y - config LV_LABEL_LONG_TXT_HINT - bool "Store extra some info in labels (12 bytes) to speed up drawing of very long texts." - depends on LV_USE_LABEL - default y - config LV_USE_LINE - bool "Line." - default y if !LV_CONF_MINIMAL - config LV_USE_ROLLER - bool "Roller. Requires: lv_label." - select LV_USE_LABEL - default y if !LV_CONF_MINIMAL - config LV_ROLLER_INF_PAGES - int "Number of extra 'pages' when the controller is infinite." - default 7 - depends on LV_USE_ROLLER - config LV_USE_SLIDER - bool "Slider. Requires: lv_bar." - select LV_USE_BAR - default y if !LV_CONF_MINIMAL - config LV_USE_SWITCH - bool "Switch." - default y if !LV_CONF_MINIMAL - config LV_USE_TEXTAREA - bool "Text area. Requires: lv_label." - select LV_USE_LABEL - default y if !LV_CONF_MINIMAL - config LV_TEXTAREA_DEF_PWD_SHOW_TIME - int "Text area def. pwd show time [ms]." - default 1500 - depends on LV_USE_TEXTAREA - config LV_USE_TABLE - bool "Table." - default y if !LV_CONF_MINIMAL - endmenu - - menu "Extra Widgets" - config LV_USE_ANIMIMG - bool "Anim image." - default y if !LV_CONF_MINIMAL - config LV_USE_CALENDAR - bool "Calendar." - default y if !LV_CONF_MINIMAL - config LV_CALENDAR_WEEK_STARTS_MONDAY - bool "Calendar week starts monday." - depends on LV_USE_CALENDAR - config LV_USE_CALENDAR_HEADER_ARROW - bool "Use calendar header arrow" - depends on LV_USE_CALENDAR - default y - config LV_USE_CALENDAR_HEADER_DROPDOWN - bool "Use calendar header dropdown" - depends on LV_USE_CALENDAR - default y - config LV_USE_CHART - bool "Chart." - default y if !LV_CONF_MINIMAL - config LV_USE_COLORWHEEL - bool "Colorwheel." - default y if !LV_CONF_MINIMAL - config LV_USE_IMGBTN - bool "Imgbtn." - default y if !LV_CONF_MINIMAL - config LV_USE_KEYBOARD - bool "Keyboard." - default y if !LV_CONF_MINIMAL - config LV_USE_LED - bool "LED." - default y if !LV_CONF_MINIMAL - config LV_USE_LIST - bool "List." - default y if !LV_CONF_MINIMAL - config LV_USE_MENU - bool "Menu." - default y if !LV_CONF_MINIMAL - config LV_USE_METER - bool "Meter." - default y if !LV_CONF_MINIMAL - config LV_USE_MSGBOX - bool "Msgbox." - default y if !LV_CONF_MINIMAL - config LV_USE_SPINBOX - bool "Spinbox." - default y if !LV_CONF_MINIMAL - config LV_USE_SPINNER - bool "Spinner." - default y if !LV_CONF_MINIMAL - config LV_USE_TABVIEW - bool "Tabview." - default y if !LV_CONF_MINIMAL - config LV_USE_TILEVIEW - bool "Tileview" - default y if !LV_CONF_MINIMAL - config LV_USE_WIN - bool "Win" - default y if !LV_CONF_MINIMAL - config LV_USE_SPAN - bool "span" - default y if !LV_CONF_MINIMAL - config LV_SPAN_SNIPPET_STACK_SIZE - int "Maximum number of span descriptor" - default 64 - depends on LV_USE_SPAN - endmenu - - menu "Themes" - config LV_USE_THEME_DEFAULT - bool "A simple, impressive and very complete theme" - default y if !LV_CONF_MINIMAL - config LV_THEME_DEFAULT_DARK - bool "Yes to set dark mode, No to set light mode" - depends on LV_USE_THEME_DEFAULT - config LV_THEME_DEFAULT_GROW - bool "Enable grow on press" - default y - depends on LV_USE_THEME_DEFAULT - config LV_THEME_DEFAULT_TRANSITION_TIME - int "Default transition time in [ms]" - default 80 - depends on LV_USE_THEME_DEFAULT - config LV_USE_THEME_BASIC - bool "A very simple theme that is a good starting point for a custom theme" - default y if !LV_CONF_MINIMAL - endmenu - - menu "Layouts" - config LV_USE_FLEX - bool "A layout similar to Flexbox in CSS." - default y if !LV_CONF_MINIMAL - config LV_USE_GRID - bool "A layout similar to Grid in CSS." - default y if !LV_CONF_MINIMAL - endmenu - - menu "3rd Party Libraries" - config LV_USE_FS_STDIO - bool "File system on top of stdio API" - config LV_FS_STDIO_LETTER - string "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65 )" - depends on LV_USE_FS_STDIO != 0 - config LV_FS_STDIO_PATH - string "Set the working directory" - depends on LV_USE_FS_STDIO != 0 - config LV_FS_STDIO_CACHE_SIZE - string ">0 to cache this number of bytes in lv_fs_read()" - depends on LV_USE_FS_STDIO != 0 - - config LV_USE_FS_POSIX - bool "File system on top of posix API" - config LV_FS_POSIX_LETTER - int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" - default 0 - depends on LV_USE_FS_POSIX != 0 - config LV_FS_POSIX_PATH - string "Set the working directory" - depends on LV_USE_FS_POSIX != 0 - config LV_FS_POSIX_CACHE_SIZE - int ">0 to cache this number of bytes in lv_fs_read()" - default 0 - depends on LV_USE_FS_POSIX != 0 - - config LV_USE_FS_WIN32 - bool "File system on top of Win32 API" - config LV_FS_WIN32_LETTER - int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" - default 0 - depends on LV_USE_FS_WIN32 != 0 - config LV_FS_WIN32_PATH - string "Set the working directory" - depends on LV_USE_FS_WIN32 != 0 - config LV_FS_WIN32_CACHE_SIZE - int ">0 to cache this number of bytes in lv_fs_read()" - default 0 - depends on LV_USE_FS_WIN32 != 0 - - config LV_USE_FS_FATFS - bool "File system on top of FatFS" - config LV_FS_FATFS_LETTER - int "Set an upper cased letter on which the drive will accessible (e.g. 'A' i.e. 65)" - default 0 - depends on LV_USE_FS_FATFS != 0 - config LV_FS_FATFS_CACHE_SIZE - int ">0 to cache this number of bytes in lv_fs_read()" - default 0 - depends on LV_USE_FS_FATFS != 0 - - config LV_USE_PNG - bool "PNG decoder library" - - config LV_USE_BMP - bool "BMP decoder library" - - config LV_USE_SJPG - bool "JPG + split JPG decoder library" - - config LV_USE_GIF - bool "GIF decoder library" - - config LV_USE_QRCODE - bool "QR code library" - - config LV_USE_FREETYPE - bool "FreeType library" - if LV_USE_FREETYPE - menu "FreeType cache config" - config LV_FREETYPE_CACHE_SIZE - int "Memory used by FreeType to cache characters [bytes] (-1: no caching)" - default 16384 - if LV_FREETYPE_CACHE_SIZE >= 0 - config LV_FREETYPE_SBIT_CACHE - bool "enable sbit cache" - default n - config LV_FREETYPE_CACHE_FT_FACES - int "The maximum number of FT_Face(0: use defaults)" - default 0 - config LV_FREETYPE_CACHE_FT_SIZES - int "The maximum number of FT_Size(0: use defaults)" - default 0 - endif - endmenu - endif - - config LV_USE_RLOTTIE - bool "Lottie library" - - config LV_USE_FFMPEG - bool "FFmpeg library" - config LV_FFMPEG_AV_DUMP_FORMAT - bool "Dump av format" - depends on LV_USE_FFMPEG - default n - endmenu - - menu "Others" - config LV_USE_SNAPSHOT - bool "Enable API to take snapshot" - default y if !LV_CONF_MINIMAL - - config LV_USE_MONKEY - bool "Enable Monkey test" - default n - endmenu - - menu "Examples" - config LV_BUILD_EXAMPLES - bool "Enable the examples to be built" - default y if !LV_CONF_MINIMAL - endmenu - - menu "Demos" - config LV_USE_DEMO_WIDGETS - bool "Show some widget" - default n - config LV_DEMO_WIDGETS_SLIDESHOW - bool "Enable slide show" - depends on LV_USE_DEMO_WIDGETS - default n - - config LV_USE_DEMO_KEYPAD_AND_ENCODER - bool "Demonstrate the usage of encoder and keyboard" - default n - - config LV_USE_DEMO_BENCHMARK - bool "Benchmark your system" - default n - - config LV_USE_DEMO_STRESS - bool "Stress test for LVGL" - default n - - config LV_USE_DEMO_MUSIC - bool "Music player demo" - default n - config LV_DEMO_MUSIC_SQUARE - bool "Enable Square" - depends on LV_USE_DEMO_MUSIC - default n - config LV_DEMO_MUSIC_LANDSCAPE - bool "Enable Landscape" - depends on LV_USE_DEMO_MUSIC - default n - config LV_DEMO_MUSIC_ROUND - bool "Enable Round" - depends on LV_USE_DEMO_MUSIC - default n - config LV_DEMO_MUSIC_LARGE - bool "Enable Large" - depends on LV_USE_DEMO_MUSIC - default n - config LV_DEMO_MUSIC_AUTO_PLAY - bool "Enable Auto play" - depends on LV_USE_DEMO_MUSIC - default n - endmenu - -endmenu diff --git a/lib/libesp32_lvgl/lvgl/README.md b/lib/libesp32_lvgl/lvgl/README.md index e8a452ee1..aea07a841 100644 --- a/lib/libesp32_lvgl/lvgl/README.md +++ b/lib/libesp32_lvgl/lvgl/README.md @@ -17,7 +17,7 @@ LVGL provides everything you need to create an embedded GUI with easy-to-use gra -**English** | [中文](./README_zh.md) | +**English** | [中文](./README_zh.md) | [Português do Brasil](./README_pt_BR.md) --- @@ -40,11 +40,11 @@ LVGL provides everything you need to create an embedded GUI with easy-to-use gra * Multi-language support with UTF-8 handling, CJK, Bidirectional and Arabic script support * Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/master/overview/style.html) * Powerful layouts inspired by CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html) -* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, and NXP PXP and VGLite) +* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, SWM341 DMA2D, and NXP PXP and VGLite) * Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/master/porting/display.html) * Written in C and compatible with C++ * Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) -* [Simulator](https://docs.lvgl.io/master/get-started/pc-simulator.html) to develop on PC without embedded hardware +* [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) to develop on PC without embedded hardware * 100+ simple [Examples](https://github.com/lvgl/lvgl/tree/master/examples) * [Documentation](http://docs.lvgl.io/) and API references online and in PDF @@ -93,26 +93,27 @@ Basically, every modern controller (which is able to drive a display) is suitabl *Note that the memory usage might vary depending on the architecture, compiler and build options.* ### Supported platforms -LVGL is completely platform independent and can be used with any MCU that fulfills the requirements. +LVGL is completely platform independent and can be used with any MCU that fulfills the requirements. Just to mention some platforms: - NXP: Kinetis, LPC, iMX, iMX RT - STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 - Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ - [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) -- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) +- [Raspberry Pi](https://github.com/lvgl/lv_port_linux_frame_buffer) - [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) - [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) - Nordic NRF52 Bluetooth modules - Quectel modems +- [SYNWIT SWM341](http://www.synwit.cn/) LVGL is also available as: -- [Arduino library](https://docs.lvgl.io/master/get-started/arduino.html) -- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl) +- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) +- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl) - [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) -- [ESP32 component](https://docs.lvgl.io/master/get-started/espressif.html) +- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) - [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) -- [NuttX library](https://docs.lvgl.io/master/get-started/nuttx.html) -- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/rt-thread.html) +- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) +- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html) ## Get started @@ -120,7 +121,7 @@ This list shows the recommended way of learning the library: 1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) 2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes) 3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes) -4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/pc-simulator.html) (10 minutes) +4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutes) 5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples) 6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_) 7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours) @@ -152,7 +153,7 @@ void btn_event_cb(lv_event_t * e) } ``` ### Micropython -Learn more about [Micropython](https://docs.lvgl.io/master/get-started/micropython.html). +Learn more about [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html). ```python def btn_event_cb(e): print("Clicked") diff --git a/lib/libesp32_lvgl/lvgl/README_pt_BR.md b/lib/libesp32_lvgl/lvgl/README_pt_BR.md new file mode 100644 index 000000000..f62f0a0f8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/README_pt_BR.md @@ -0,0 +1,206 @@ +

LVGL - Biblioteca gráfica leve e versátil

+

+ +

+

+ O LVGL fornece tudo o que você precisa para criar uma GUI incorporada com elementos gráficos fáceis de usar, belos efeitos visuais e um baixo consumo de memória. +

+

+ Site · + Documentação · + Fórum · + Serviços · + Exemplos interativos +

+ +[English](./README.md) | [中文](./README_zh.md) | **Português do Brasil** + +--- + +### Tabela de conteúdo + +- [Visão Geral](#visão-geral) +- [Iniciando](#iniciando) +- [Exemplos](#exemplos) +- [Serviços](#serviços) +- [Contribuindo](#contribuindo) + +## Visão Geral + +### Recursos +* Poderosos [widgets](https://docs.lvgl.io/master/widgets/index.html): botões, gráficos, listas, controles deslizantes (sliders), imagens, etc. +* Mecanismo gráfico avançado: animações, anti-aliasing, opacidade, rolagem suave, modos de mesclagem (blending modes), etc. +* Suporte à [vários dispositivos de entrada](https://docs.lvgl.io/master/overview/indev.html): tela sensível ao toque, mouse, teclado, codificador, botões, etc. +* Suporte à [vários monitores](https://docs.lvgl.io/master/overview/display.html) +* Pode ser usado com qualquer microcontrolador e display, independente do hardware +* Escalável para operar com pouca memória (64 kB Flash, 16 kB RAM) +* Suporte multilíngue com manipulação UTF-8, suporte ao alfabeto bidirecional, árabe e CJK (Chinês, Japonês e Coreano) +* Elementos gráficos totalmente personalizáveis por meio de [CSS](https://docs.lvgl.io/master/overview/style.html) +* Layouts poderosos inspirados em CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) e [Grid](https://docs.lvgl.io/master/layouts/grid.html) +* SO, memória externa e GPU são suportados, mas não obrigatórios. (suporte integrado para STM32 DMA2D, SWM341 DMA2D e NXP PXP e VGLite) +* Renderização suave mesmo com um [buffer de quadro único](https://docs.lvgl.io/master/porting/display.html) (single frame buffer) +* Escrito em C e compatível com C++ +* Uso do LittlevGL com Micropython simplificado com [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) +* [Simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) para desenvolver no PC sem hardware embutido +* Mais de 100 [exemplos simples](https://github.com/lvgl/lvgl/tree/master/examples) +* [Documentação](http://docs.lvgl.io/) e referências de API online e em PDF + +### Requerimentos +Basicamente, todo controlador moderno (que é capaz de acionar um display) é adequado para executar LVGL. Os requisitos mínimos são: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Nome + + Minímo + + Recomendado +
+ Arquitetura + Microcontrolador ou processador de 16, 32 ou 64 bits
+ Clock + > 16 MHz> 48 MHz
+ Flash/ROM + > 64 kB> 180 kB
+ RAM estática + > 16 kB> 48 kB
+ Draw buffer + > 1 × hor. res. pixels> tamanho da tela de 1/10
+ Compilador + Padrão C99 ou mais recente
+ +*Observe que o uso de memória pode variar dependendo da arquitetura, do compilador e das opções de compilação.* + +### Plataformas suportadas +O LVGL é completamente independente de plataforma e pode ser usado com qualquer MCU que atenda aos requisitos. +Apenas para citar algumas plataformas: + +- NXP: Kinetis, LPC, iMX, iMX RT +- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 +- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ +- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) +- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) +- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) +- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) +- Nordic NRF52 Bluetooth modules +- Quectel modems +- [SYNWIT SWM341](https://www.synwit.cn/) + +LVGL também está disponível para: +- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) +- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl) +- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) +- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) +- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) +- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) +- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html) + +## Iniciando +Esta lista mostra a maneira recomendada de aprender sobre a biblioteca: + +1. Confira as [demos on-line](https://lvgl.io/demos) para ver o LVGL em ação (3 minutos) +2. Leia a [introdução](https://docs.lvgl.io/master/intro/index.html) da documentação (5 minutos) +3. Familiarize-se com o básico da [Visão geral rápida](https://docs.lvgl.io/master/get-started/quick-overview.html) (15 minutos) +4. Configure um [simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutos) +5. Experimente alguns [Exemplos](https://github.com/lvgl/lvgl/tree/master/examples) +6. Placa para porta LVGL. Veja o guia [porting](https://docs.lvgl.io/master/porting/index.html) ou verifique o pronto para usar [Projects](https://github.com/lvgl?q=lv_port_) +7. Leia a [visão geral](https://docs.lvgl.io/master/overview/index.html) para entender melhor a biblioteca (2-3 horas) +8. Verifique a documentação dos [widgets](https://docs.lvgl.io/master/widgets/index.html) para ver seus recursos e como utilizá-los +9. Se você tiver dúvidas, acesse o [fórum](http://forum.lvgl.io/) +10. Leia o guia de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) para ver como você pode ajudar a melhorar o LVGL (15 minutos) + +## Exemplos +Para mais exemplos, veja a pasta [examples](https://github.com/lvgl/lvgl/tree/master/examples). + +![Exemplo de botão LVGL com rótulo (label)](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) + +### C + +```c +lv_obj_t * button = lv_btn_create(lv_scr_act()); /* Adiciona um botão à tela atual */ +lv_obj_set_pos(button, 10, 10); /* Define uma posição ao botão na tela */ +lv_obj_set_size(button, 100, 50); /* Define o tamanho */ +lv_obj_add_event_cb(button, button_event_callback, LV_EVENT_CLICKED, NULL); /* Atribui um retorno de chamada (callback) */ + +lv_obj_t * label = lv_label_create(button); /* Adiciona um rótulo (label) */ +lv_label_set_text(label, "Clique aqui"); /* Define o texto do rótulo (label) */ +lv_obj_center(label); /* Alinha o texto ao centro */ +... + +void button_event_callback(lv_event_t * e) +{ + printf("Clicado\n"); +} +``` + +### Micropython +Saiba mais em [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html) + +```python +def button_event_callback(event): + print("Clicado") + +# Cria um botão e um rótulo (label) +button = lv.btn(lv.scr_act()) +button.set_pos(10, 10) +button.set_size(100, 50) +button.add_event_cb(button_event_callback, lv.EVENT.CLICKED, None) + +label = lv.label(button) +label.set_text("Cliquq aqui") +label.center() +``` + +## Serviços +O LVGL Kft foi estabelecido para fornecer uma base sólida para a biblioteca LVGL. Oferecemos vários tipos de serviços +para ajudá-lo no desenvolvimento da interface do usuário: + +- Design gráfico +- Implementação de IU +- Consultoria/Suporte + +Para mais informações, consulte [LVGL Serviços](https://lvgl.io/services). Sinta-se à vontade para entrar em contato +conosco se tiver alguma dúvida. + +## Contribuindo +O LVGL é um projeto aberto e sua contribuição é muito bem-vinda. Há muitas maneiras de contribuir, desde simplesmente +falando sobre seu projeto, escrevendo exemplos, melhorando a documentação, corrigindo bugs até hospedar seu próprio +projeto sob a organização LVGL. + +Para obter uma descrição detalhada das oportunidades de contribuição, visite a seção de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) da documentação. diff --git a/lib/libesp32_lvgl/lvgl/README_zh.md b/lib/libesp32_lvgl/lvgl/README_zh.md new file mode 100644 index 000000000..cac080d4e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/README_zh.md @@ -0,0 +1,193 @@ +

LVGL - Light and Versatile Graphics Library

+

LVGL - 轻量级通用型图形库

+ + + +

+ +

+

+LVGL是一个高度可裁剪、低资源占用、界面美观且易用的嵌入式系统图形库 +

+ + +

+官网 · +文档 · +论坛 · +服务 · +例程 +

+ + +[English](./README.md) | **中文** | [Português do Brasil](./README_pt_BR.md) + + +--- + +#### 目录 +- [概况与总览](#概况与总览) +- [如何入门](#如何入门) +- [例程](#例程) +- [服务](#服务) +- [如何向社区贡献](#如何向社区贡献) + +## 概况与总览 +### 特性 +* 丰富且强大的模块化[图形组件](https://docs.lvgl.io/master/widgets/index.html):按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等 +* 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果 +* 支持多种[输入设备](https://docs.lvgl.io/master/overview/indev.html):触摸屏、 键盘、编码器、按键等 +* 支持[多显示设备](https://docs.lvgl.io/master/overview/display.html) +* 不依赖特定的硬件平台,可以在任何显示屏上运行 +* 配置可裁剪(最低资源占用:64 kB Flash,16 kB RAM) +* 基于UTF-8的多语种支持,例如中文、日文、韩文、阿拉伯文等 +* 可以通过[类CSS](https://docs.lvgl.io/master/overview/style.html)的方式来设计、布局图形界面(例如:[Flexbox](https://docs.lvgl.io/master/layouts/flex.html)、[Grid](https://docs.lvgl.io/master/layouts/grid.html)) +* 支持操作系统、外置内存、以及硬件加速(LVGL已内建支持STM32 DMA2D、SWM341 DMA2D、NXP PXP和VGLite) +* 即便仅有[单缓冲区(frame buffer)](https://docs.lvgl.io/master/porting/display.html)的情况下,也可保证渲染如丝般顺滑 +* 全部由C编写完成,并支持C++调用 +* 支持Micropython编程,参见:[LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) +* 支持[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)仿真,可以无硬件依托进行开发 +* 丰富详实的[例程](https://github.com/lvgl/lvgl/tree/master/examples) +* 详尽的[文档](http://docs.lvgl.io/)以及API参考手册,可线上查阅或可下载为PDF格式 + +### 硬件要求 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
要求 最低要求建议要求
架构16、32、64位微控制器或微处理器
时钟 > 16 MHz > 48 MHz
Flash/ROM > 64 kB > 180 kB
Static RAM > 16 kB > 48 kB
Draw buffer > 1 × hor. res. pixels > 1/10屏幕大小
编译器 C99或更新
+ +*注意:资源占用情况与具体硬件平台、编译器等因素有关,上表中仅给出参考值* + +### 已经支持的平台 +LVGL本身并不依赖特定的硬件平台,任何满足LVGL硬件配置要求的微控制器均可运行LVGL。 +如下仅列举其中一部分: + +- NXP: Kinetis, LPC, iMX, iMX RT +- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 +- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ +- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) +- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) +- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) +- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) +- Nordic NRF52 Bluetooth modules +- Quectel modems +- [SYNWIT SWM341](https://www.synwit.cn/) + +LVGL也支持: +- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) +- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl) +- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) +- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) +- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) +- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) +- [RT-Thread RTOS](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/introduction) + + +## 如何入门 +请按照如下顺序来学习LVGL: +1. 使用[网页在线例程](https://lvgl.io/demos)来体验LVGL(3分钟) +2. 阅读文档[简介](https://docs.lvgl.io/master/intro/index.html)章节来初步了解LVGL(5分钟) +3. 再来阅读一下文档快速[快速概览](https://docs.lvgl.io/master/get-started/quick-overview.html)章节来了解LVGL的基本知识(15分钟) +4. 学习如何使用[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)来在电脑上仿真LVGL(10分钟) +5. 试着动手实践一些[例程](https://github.com/lvgl/lvgl/tree/master/examples) +6. 参考[移植指南](https://docs.lvgl.io/master/porting/index.html)尝试将LVGL移植到一块开发板上,LVGL也已经提供了一些移植好的[工程](https://github.com/lvgl?q=lv_port_) +7. 仔细阅读文档[总览](https://docs.lvgl.io/master/overview/index.html)章节来更加深入的了解和熟悉LVGL(2-3小时) +8. 浏览文档[组件(Widgets)](https://docs.lvgl.io/master/widgets/index.html)章节来了解如何使用它们 +9. 如果你有问题可以到LVGL[论坛](http://forum.lvgl.io/)提问 +10. 阅读文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来看看你能帮LVGL社区做些什么,以促进LVGL软件质量的不断提高(15分钟) + +## 例程 + +更多例程请参见 [examples](https://github.com/lvgl/lvgl/tree/master/examples) 文件夹。 + +![LVGL button with label example](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) + +### C +```c +lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/ +lv_obj_set_pos(btn, 10, 10); /*Set its position*/ +lv_obj_set_size(btn, 100, 50); /*Set its size*/ +lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/ + +lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/ +lv_label_set_text(label, "Button"); /*Set the labels text*/ +lv_obj_center(label); /*Align the label to the center*/ +... + +void btn_event_cb(lv_event_t * e) +{ + printf("Clicked\n"); +} +``` +### Micropython +更多信息请到 [Micropython官网](https://docs.lvgl.io/master/get-started/bindings/micropython.html) 查询. +```python +def btn_event_cb(e): + print("Clicked") + +# Create a Button and a Label +btn = lv.btn(lv.scr_act()) +btn.set_pos(10, 10) +btn.set_size(100, 50) +btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None) + +label = lv.label(btn) +label.set_text("Button") +label.center() +``` + +## 服务 +LVGL 责任有限公司成立的目的是为了给用户使用LVGL图形库提供额外的技术支持,我们致力于提供以下服务: + +- 图形设计 +- UI设计 +- 技术咨询以及技术支持 + +更多信息请参见 https://lvgl.io/services ,如果有任何问题请随时联系我们。 + + +## 如何向社区贡献 +LVGL是一个开源项目,非常欢迎您参与到社区贡献当中。您有很多种方式来为提高LVGL贡献您的一份力量,包括但不限于: + +- 介绍你基于LVGL设计的作品或项目 +- 写一些例程 +- 修改以及完善文档 +- 修复bug + +请参见文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来获取更多信息。 diff --git a/lib/libesp32_lvgl/lvgl/library.json b/lib/libesp32_lvgl/lvgl/library.json index 79cf2c0e1..7a475b1ce 100644 --- a/lib/libesp32_lvgl/lvgl/library.json +++ b/lib/libesp32_lvgl/lvgl/library.json @@ -1,6 +1,6 @@ { "name": "lvgl", - "version": "8.2.0", + "version": "8.3.0", "keywords": "graphics, gui, embedded, tft, lvgl", "description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.", "repository": { diff --git a/lib/libesp32_lvgl/lvgl/library.properties b/lib/libesp32_lvgl/lvgl/library.properties index 99a97ed6e..4b27e7d96 100644 --- a/lib/libesp32_lvgl/lvgl/library.properties +++ b/lib/libesp32_lvgl/lvgl/library.properties @@ -1,5 +1,5 @@ name=lvgl -version=8.2.0 +version=8.3.0 author=kisvegabor maintainer=kisvegabor,embeddedt,pete-pjb sentence=Full-featured Graphics Library for Embedded Systems diff --git a/lib/libesp32_lvgl/lvgl/lv_conf_template.h b/lib/libesp32_lvgl/lvgl/lv_conf_template.h index c268d269b..03a4ec353 100644 --- a/lib/libesp32_lvgl/lvgl/lv_conf_template.h +++ b/lib/libesp32_lvgl/lvgl/lv_conf_template.h @@ -1,6 +1,6 @@ /** * @file lv_conf.h - * Configuration file for v8.2.0 + * Configuration file for v8.3.0 */ /* @@ -29,14 +29,14 @@ /*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ #define LV_COLOR_16_SWAP 0 -/*Enable more complex drawing routines to manage screens transparency. - *Can be used if the UI is above another layer, e.g. an OSD menu or video player. - *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ +/*Enable features to draw on transparent background. + *It's required if opa, and transform_* style properties are used. + *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ #define LV_COLOR_SCREEN_TRANSP 0 /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ -#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) +#define LV_COLOR_MIX_ROUND_OFS 0 /*Images pixels with this color will not be drawn if they are chroma keyed)*/ #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ @@ -55,8 +55,8 @@ #define LV_MEM_ADR 0 /*0: unused*/ /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ #if LV_MEM_ADR == 0 - //#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ - //#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ + #undef LV_MEM_POOL_INCLUDE + #undef LV_MEM_POOL_ALLOC #endif #else /*LV_MEM_CUSTOM*/ @@ -120,33 +120,49 @@ #define LV_CIRCLE_CACHE_SIZE 4 #endif /*LV_DRAW_COMPLEX*/ +/** + * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer + * and blend it as an image with the given opacity. + * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) + * The widget can be buffered in smaller chunks to avoid using large buffers. + * + * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it + * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. + * + * Both buffer sizes are in bytes. + * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers + * and can't be drawn in chunks. So these settings affects only widgets with opacity. + */ +#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) +#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) + /*Default image cache size. Image caching keeps the images opened. *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. *However the opened images might consume additional RAM. *0: to disable caching*/ -#define LV_IMG_CACHE_DEF_SIZE 0 +#define LV_IMG_CACHE_DEF_SIZE 0 /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ -#define LV_GRADIENT_MAX_STOPS 2 +#define LV_GRADIENT_MAX_STOPS 2 /*Default gradient buffer size. *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. *If the cache is too small the map will be allocated only while it's required for the drawing. *0 mean no caching.*/ -#define LV_GRAD_CACHE_DEF_SIZE 0 +#define LV_GRAD_CACHE_DEF_SIZE 0 /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 0 +#define LV_DITHER_GRADIENT 0 #if LV_DITHER_GRADIENT /*Add support for error diffusion dithering. *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. *The increase in memory consumption is (24 bits * object's width)*/ - #define LV_DITHER_ERROR_DIFFUSION 0 + #define LV_DITHER_ERROR_DIFFUSION 0 #endif /*Maximum buffer size to allocate for rotation. @@ -157,6 +173,9 @@ * GPU *-----------*/ +/*Use Arm's 2D acceleration library Arm-2D */ +#define LV_USE_GPU_ARM2D 0 + /*Use STM32's DMA2D (aka Chrom Art) GPU*/ #define LV_USE_GPU_STM32_DMA2D 0 #if LV_USE_GPU_STM32_DMA2D @@ -165,6 +184,12 @@ #define LV_GPU_DMA2D_CMSIS_INCLUDE #endif +/*Use SWM341's DMA2D GPU*/ +#define LV_USE_GPU_SWM341_DMA2D 0 +#if LV_USE_GPU_SWM341_DMA2D + #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" +#endif + /*Use NXP's PXP GPU iMX RTxxx platforms*/ #define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP @@ -380,6 +405,9 @@ #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ #endif +/*Enable drawing placeholders when glyph dsc is not found*/ +#define LV_USE_FONT_PLACEHOLDER 1 + /*================= * TEXT SETTINGS *=================*/ @@ -434,8 +462,6 @@ #define LV_USE_ARC 1 -#define LV_USE_ANIMIMG 1 - #define LV_USE_BAR 1 #define LV_USE_BTN 1 @@ -481,6 +507,8 @@ /*----------- * Widgets *----------*/ +#define LV_USE_ANIMIMG 1 + #define LV_USE_CALENDAR 1 #if LV_USE_CALENDAR #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 @@ -513,6 +541,12 @@ #define LV_USE_MSGBOX 1 +#define LV_USE_SPAN 1 +#if LV_USE_SPAN + /*A line text can contain maximum num of span descriptor */ + #define LV_SPAN_SNIPPET_STACK_SIZE 64 +#endif + #define LV_USE_SPINBOX 1 #define LV_USE_SPINNER 1 @@ -523,12 +557,6 @@ #define LV_USE_WIN 1 -#define LV_USE_SPAN 1 -#if LV_USE_SPAN - /*A line text can contain maximum num of span descriptor */ - #define LV_SPAN_SNIPPET_STACK_SIZE 64 -#endif - /*----------- * Themes *----------*/ @@ -574,7 +602,7 @@ #if LV_USE_FS_STDIO #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ - #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for open, read, etc*/ @@ -582,19 +610,19 @@ #if LV_USE_FS_POSIX #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ - #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for CreateFile, ReadFile, etc*/ #define LV_USE_FS_WIN32 0 #if LV_USE_FS_WIN32 - #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ -#define LV_USE_FS_FATFS 0 +#define LV_USE_FS_FATFS 0 #if LV_USE_FS_FATFS #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ @@ -638,10 +666,10 @@ /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ -#define LV_USE_FFMPEG 0 +#define LV_USE_FFMPEG 0 #if LV_USE_FFMPEG /*Dump input information to stderr*/ - #define LV_FFMPEG_AV_DUMP_FORMAT 0 + #define LV_FFMPEG_DUMP_FORMAT 0 #endif /*----------- @@ -652,10 +680,37 @@ #define LV_USE_SNAPSHOT 0 /*1: Enable Monkey test*/ -#define LV_USE_MONKEY 0 +#define LV_USE_MONKEY 0 /*1: Enable grid navigation*/ -#define LV_USE_GRIDNAV 0 +#define LV_USE_GRIDNAV 0 + +/*1: Enable lv_obj fragment*/ +#define LV_USE_FRAGMENT 0 + +/*1: Support using images as font in label or span widgets */ +#define LV_USE_IMGFONT 0 + +/*1: Enable a published subscriber based messaging system */ +#define LV_USE_MSG 0 + +/*1: Enable Pinyin input method*/ +/*Requires: lv_keyboard*/ +#define LV_USE_IME_PINYIN 0 +#if LV_USE_IME_PINYIN + /*1: Use default thesaurus*/ + /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ + #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 + /*Set the maximum number of candidate panels that can be displayed*/ + /*This needs to be adjusted according to the size of the screen*/ + #define LV_IME_PINYIN_CAND_TEXT_NUM 6 + + /*Use 9 key input(k9)*/ + #define LV_IME_PINYIN_USE_K9_MODE 1 + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif // LV_IME_PINYIN_USE_K9_MODE +#endif /*================== * EXAMPLES @@ -669,28 +724,32 @@ ====================*/ /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ -#define LV_USE_DEMO_WIDGETS 0 +#define LV_USE_DEMO_WIDGETS 0 #if LV_USE_DEMO_WIDGETS -#define LV_DEMO_WIDGETS_SLIDESHOW 0 +#define LV_DEMO_WIDGETS_SLIDESHOW 0 #endif /*Demonstrate the usage of encoder and keyboard*/ -#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 +#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 /*Benchmark your system*/ -#define LV_USE_DEMO_BENCHMARK 0 +#define LV_USE_DEMO_BENCHMARK 0 +#if LV_USE_DEMO_BENCHMARK +/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ +#define LV_DEMO_BENCHMARK_RGB565A8 0 +#endif /*Stress test for LVGL*/ -#define LV_USE_DEMO_STRESS 0 +#define LV_USE_DEMO_STRESS 0 /*Music player demo*/ -#define LV_USE_DEMO_MUSIC 0 +#define LV_USE_DEMO_MUSIC 0 #if LV_USE_DEMO_MUSIC -# define LV_DEMO_MUSIC_SQUARE 0 -# define LV_DEMO_MUSIC_LANDSCAPE 0 -# define LV_DEMO_MUSIC_ROUND 0 -# define LV_DEMO_MUSIC_LARGE 0 -# define LV_DEMO_MUSIC_AUTO_PLAY 0 + #define LV_DEMO_MUSIC_SQUARE 0 + #define LV_DEMO_MUSIC_LANDSCAPE 0 + #define LV_DEMO_MUSIC_ROUND 0 + #define LV_DEMO_MUSIC_LARGE 0 + #define LV_DEMO_MUSIC_AUTO_PLAY 0 #endif /*--END OF LV_CONF_H--*/ diff --git a/lib/libesp32_lvgl/lvgl/lvgl.h b/lib/libesp32_lvgl/lvgl/lvgl.h index df96d213d..315764416 100644 --- a/lib/libesp32_lvgl/lvgl/lvgl.h +++ b/lib/libesp32_lvgl/lvgl/lvgl.h @@ -14,7 +14,7 @@ extern "C" { * CURRENT VERSION OF LVGL ***************************/ #define LVGL_VERSION_MAJOR 8 -#define LVGL_VERSION_MINOR 2 +#define LVGL_VERSION_MINOR 3 #define LVGL_VERSION_PATCH 0 #define LVGL_VERSION_INFO "" @@ -67,11 +67,6 @@ extern "C" { * EXTRAS *----------------*/ #include "src/extra/lv_extra.h" -#include "src/extra/widgets/lv_widgets.h" -#include "src/extra/layouts/lv_layouts.h" -#include "src/extra/themes/lv_themes.h" -#include "src/extra/others/lv_others.h" -#include "src/extra/libs/lv_libs.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/lvgl/lvgl.mk b/lib/libesp32_lvgl/lvgl/lvgl.mk deleted file mode 100644 index a57c1d2bb..000000000 --- a/lib/libesp32_lvgl/lvgl/lvgl.mk +++ /dev/null @@ -1,10 +0,0 @@ -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/demos/lv_demos.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/examples/examples.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/extra.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core/lv_core.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/lv_draw.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/font/lv_font.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/hal/lv_hal.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/misc/lv_misc.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/widgets/lv_widgets.mk diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c index 2806c4e7b..a1022b56c 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c @@ -21,12 +21,13 @@ /********************** * STATIC PROTOTYPES **********************/ - +static void scr_load_internal(lv_obj_t * scr); static void scr_load_anim_start(lv_anim_t * a); static void opa_scale_anim(void * obj, int32_t v); static void set_x_anim(void * obj, int32_t v); static void set_y_anim(void * obj, int32_t v); static void scr_anim_ready(lv_anim_t * a); +static bool is_out_anim(lv_scr_load_anim_t a); /********************** * STATIC VARIABLES @@ -80,20 +81,7 @@ lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp) */ void lv_disp_load_scr(lv_obj_t * scr) { - lv_disp_t * d = lv_obj_get_disp(scr); - if(!d) return; /*Shouldn't happen, just to be sure*/ - - lv_obj_t * old_scr = d->act_scr; - - if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); - if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL); - - d->act_scr = scr; - - if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL); - if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); - - lv_obj_invalidate(scr); + lv_scr_load_anim(scr, LV_SCR_LOAD_ANIM_NONE, 0, 0, false); } /** @@ -135,7 +123,12 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) */ void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th) { - if(disp == NULL) disp = lv_disp_get_default(); + if(!disp) disp = lv_disp_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return; + } + disp->theme = th; if(disp->screen_cnt == 3 && @@ -220,7 +213,7 @@ void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa) /** * Switch screen with animation * @param scr pointer to the new screen to load - * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` * @param time time of the animation * @param delay delay before the transition * @param auto_del true: automatically delete the old screen @@ -234,7 +227,7 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t /*If an other screen load animation is in progress *make target screen loaded immediately. */ if(d->scr_to_load && act_scr != d->scr_to_load) { - lv_disp_load_scr(d->scr_to_load); + scr_load_internal(d->scr_to_load); lv_anim_del(d->scr_to_load, NULL); lv_obj_set_pos(d->scr_to_load, 0, 0); lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0); @@ -252,6 +245,7 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t d->prev_scr = NULL; } + d->draw_prev_over_act = is_out_anim(anim_type); d->del_prev = auto_del; /*Be sure there is no other animation on the screens*/ @@ -264,6 +258,13 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0); lv_obj_remove_local_style_prop(lv_scr_act(), LV_STYLE_OPA, 0); + + /*Shortcut for immediate load*/ + if(time == 0 && delay == 0) { + scr_load_internal(new_scr); + return; + } + lv_anim_t a_new; lv_anim_init(&a_new); lv_anim_set_var(&a_new, new_scr); @@ -328,18 +329,36 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t lv_anim_set_exec_cb(&a_old, set_y_anim); lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d)); break; - - case LV_SCR_LOAD_ANIM_FADE_ON: + case LV_SCR_LOAD_ANIM_FADE_IN: lv_anim_set_exec_cb(&a_new, opa_scale_anim); lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER); break; + case LV_SCR_LOAD_ANIM_FADE_OUT: + lv_anim_set_exec_cb(&a_old, opa_scale_anim); + lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP); + break; + case LV_SCR_LOAD_ANIM_OUT_LEFT: + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_RIGHT: + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_TOP: + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_BOTTOM: + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d)); + break; } lv_event_send(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); lv_anim_start(&a_new); lv_anim_start(&a_old); - } /** @@ -394,6 +413,38 @@ void lv_disp_clean_dcache(lv_disp_t * disp) disp->driver->clean_dcache_cb(disp->driver); } +/** + * Temporarily enable and disable the invalidation of the display. + * @param disp pointer to a display (NULL to use the default display) + * @param en true: enable invalidation; false: invalidation + */ +void lv_disp_enable_invalidation(lv_disp_t * disp, bool en) +{ + if(!disp) disp = lv_disp_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return; + } + + disp->inv_en_cnt += en ? 1 : -1; +} + +/** + * Get display invalidation is enabled. + * @param disp pointer to a display (NULL to use the default display) + * @return return true if invalidation is enabled + */ +bool lv_disp_is_invalidation_enabled(lv_disp_t * disp) +{ + if(!disp) disp = lv_disp_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return false; + } + + return (disp->inv_en_cnt > 0); +} + /** * Get a pointer to the screen refresher timer to * modify its parameters with `lv_timer_...` functions. @@ -415,6 +466,24 @@ lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp) * STATIC FUNCTIONS **********************/ +static void scr_load_internal(lv_obj_t * scr) +{ + lv_disp_t * d = lv_obj_get_disp(scr); + if(!d) return; /*Shouldn't happen, just to be sure*/ + + lv_obj_t * old_scr = d->act_scr; + + if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL); + + d->act_scr = scr; + + if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL); + if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + + lv_obj_invalidate(scr); +} + static void scr_load_anim_start(lv_anim_t * a) { lv_disp_t * d = lv_obj_get_disp(a->var); @@ -449,6 +518,17 @@ static void scr_anim_ready(lv_anim_t * a) if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr); d->prev_scr = NULL; + d->draw_prev_over_act = false; d->scr_to_load = NULL; lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0); + lv_obj_invalidate(d->act_scr); +} + +static bool is_out_anim(lv_scr_load_anim_t anim_type) +{ + return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT || + anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT || + anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT || + anim_type == LV_SCR_LOAD_ANIM_OUT_TOP || + anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM; } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h index 01766b345..7854cb7f2 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h @@ -35,7 +35,13 @@ typedef enum { LV_SCR_LOAD_ANIM_MOVE_RIGHT, LV_SCR_LOAD_ANIM_MOVE_TOP, LV_SCR_LOAD_ANIM_MOVE_BOTTOM, - LV_SCR_LOAD_ANIM_FADE_ON, + LV_SCR_LOAD_ANIM_FADE_IN, + LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/ + LV_SCR_LOAD_ANIM_FADE_OUT, + LV_SCR_LOAD_ANIM_OUT_LEFT, + LV_SCR_LOAD_ANIM_OUT_RIGHT, + LV_SCR_LOAD_ANIM_OUT_TOP, + LV_SCR_LOAD_ANIM_OUT_BOTTOM, } lv_scr_load_anim_t; /********************** @@ -116,7 +122,7 @@ void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa); /** * Switch screen with animation * @param scr pointer to the new screen to load - * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` * @param time time of the animation * @param delay delay before the transition * @param auto_del true: automatically delete the old screen @@ -142,6 +148,20 @@ void lv_disp_trig_activity(lv_disp_t * disp); */ void lv_disp_clean_dcache(lv_disp_t * disp); +/** + * Temporarily enable and disable the invalidation of the display. + * @param disp pointer to a display (NULL to use the default display) + * @param en true: enable invalidation; false: invalidation + */ +void lv_disp_enable_invalidation(lv_disp_t * disp, bool en); + +/** + * Get display invalidation is enabled. + * @param disp pointer to a display (NULL to use the default display) + * @return return true if invalidation is enabled + */ +bool lv_disp_is_invalidation_enabled(lv_disp_t * disp); + /** * Get a pointer to the screen refresher timer to * modify its parameters with `lv_timer_...` functions. diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_event.c b/lib/libesp32_lvgl/lvgl/src/core/lv_event.c index 143ff34b8..f53ceac1d 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_event.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_event.c @@ -208,7 +208,7 @@ bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_c int32_t i = 0; for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb) && + if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) && obj->spec_attr->event_dsc[i].user_data == user_data) { /*Shift the remaining event handlers forward*/ for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { @@ -254,7 +254,7 @@ bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb) { LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; + if(obj->spec_attr == NULL) return NULL; int32_t i = 0; for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { @@ -436,7 +436,7 @@ static lv_res_t event_send_core(lv_event_t * e) } lv_res_t res = LV_RES_OK; - lv_event_dsc_t * event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0); + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0); uint32_t i = 0; while(event_dsc && res == LV_RES_OK) { diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_event.h b/lib/libesp32_lvgl/lvgl/src/core/lv_event.h index 038570b72..d5a9eb6ba 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_event.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_event.h @@ -41,7 +41,7 @@ typedef enum { LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ - LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins*/ + LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/ LV_EVENT_SCROLL_END, /**< Scrolling ends*/ LV_EVENT_SCROLL, /**< Scrolling*/ LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_group.c b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c index 3e13b0b79..242c9d1c4 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_group.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c @@ -24,7 +24,7 @@ /********************** * STATIC PROTOTYPES **********************/ -static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), +static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), void * (*move)(const lv_ll_t *, const void *)); static void lv_group_refocus(lv_group_t * g); static lv_indev_t * get_indev(const lv_group_t * g); @@ -57,6 +57,7 @@ lv_group_t * lv_group_create(void) group->obj_focus = NULL; group->frozen = 0; group->focus_cb = NULL; + group->edge_cb = NULL; group->editing = 0; group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV; group->wrap = 1; @@ -261,12 +262,20 @@ void lv_group_focus_obj(lv_obj_t * obj) void lv_group_focus_next(lv_group_t * group) { - focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next); + bool focus_changed = focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next); + if(group->edge_cb) { + if(!focus_changed) + group->edge_cb(group, true); + } } void lv_group_focus_prev(lv_group_t * group) { - focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev); + bool focus_changed = focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev); + if(group->edge_cb) { + if(!focus_changed) + group->edge_cb(group, false); + } } void lv_group_focus_freeze(lv_group_t * group, bool en) @@ -279,6 +288,9 @@ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) { lv_obj_t * act = lv_group_get_focused(group); if(act == NULL) return LV_RES_OK; + + if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RES_OK; + return lv_event_send(act, LV_EVENT_KEY, &c); } @@ -287,6 +299,11 @@ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) group->focus_cb = focus_cb; } +void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb) +{ + group->edge_cb = edge_cb; +} + void lv_group_set_editing(lv_group_t * group, bool edit) { if(group == NULL) return; @@ -329,6 +346,12 @@ lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group) return group->focus_cb; } +lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group) +{ + if(!group) return NULL; + return group->edge_cb; +} + bool lv_group_get_editing(const lv_group_t * group) { if(!group) return false; @@ -363,10 +386,11 @@ static void lv_group_refocus(lv_group_t * g) g->wrap = temp_wrap; } -static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), +static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), void * (*move)(const lv_ll_t *, const void *)) { - if(group->frozen) return; + bool focus_changed = false; + if(group->frozen) return focus_changed; lv_obj_t ** obj_next = group->obj_focus; lv_obj_t ** obj_sentinel = NULL; @@ -376,27 +400,27 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) for(;;) { if(obj_next == NULL) { if(group->wrap || obj_sentinel == NULL) { - if(!can_begin) return; + if(!can_begin) return focus_changed; obj_next = begin(&group->obj_ll); can_move = false; can_begin = false; } else { /*Currently focused object is the last/first in the group, keep it that way*/ - return; + return focus_changed; } } if(obj_sentinel == NULL) { obj_sentinel = obj_next; - if(obj_sentinel == NULL) return; /*Group is empty*/ + if(obj_sentinel == NULL) return focus_changed; /*Group is empty*/ } if(can_move) { obj_next = move(&group->obj_ll, obj_next); /*Give up if we walked the entire list and haven't found another visible object*/ - if(obj_next == obj_sentinel) return; + if(obj_next == obj_sentinel) return focus_changed; } can_move = true; @@ -418,22 +442,24 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) break; } - if(obj_next == group->obj_focus) return; /*There's only one visible object and it's already focused*/ + if(obj_next == group->obj_focus) return focus_changed; /*There's only one visible object and it's already focused*/ if(group->obj_focus) { lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); - if(res != LV_RES_OK) return; + if(res != LV_RES_OK) return focus_changed; lv_obj_invalidate(*group->obj_focus); } group->obj_focus = obj_next; lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group)); - if(res != LV_RES_OK) return; + if(res != LV_RES_OK) return focus_changed; lv_obj_invalidate(*group->obj_focus); if(group->focus_cb) group->focus_cb(group); + focus_changed = true; + return focus_changed; } /** diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_group.h b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h index ecf88df6b..091059730 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_group.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h @@ -50,6 +50,7 @@ struct _lv_obj_t; struct _lv_group_t; typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); +typedef void (*lv_group_edge_cb_t)(struct _lv_group_t *, bool); /** * Groups can be used to logically hold objects so that they can be individually focused. @@ -60,6 +61,10 @@ typedef struct _lv_group_t { struct _lv_obj_t ** obj_focus; /**< The object in focus*/ lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/ + lv_group_edge_cb_t edge_cb; /**< A function to call when an edge is reached, no more focus + targets are available in this direction (to allow edge feedback + like a sound or a scroll bounce) */ + #if LV_USE_USER_DATA void * user_data; #endif @@ -178,6 +183,14 @@ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c); */ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb); +/** + * Set a function for a group which will be called when a focus edge is reached + * @param group pointer to a group + * @param edge_cb the call back function or NULL if unused + */ +void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb); + + /** * Set whether the next or previous item in a group is focused if the currently focused obj is * deleted. @@ -214,6 +227,13 @@ struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group); */ lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group); +/** + * Get the edge callback function of a group + * @param group pointer to a group + * @return the call back function or NULL if not set + */ +lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group); + /** * Get the current mode (edit or navigate). * @param group pointer to group diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c index 079aa943c..ab1265ec8 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c @@ -75,14 +75,15 @@ void lv_indev_read_timer_cb(lv_timer_t * timer) /*Handle reset query before processing the point*/ indev_proc_reset_query_handler(indev_act); - if(indev_act->proc.disabled) return; + if(indev_act->proc.disabled || + indev_act->driver->disp->prev_scr != NULL) return; /*Input disabled or screen animation active*/ bool continue_reading; do { /*Read the data*/ _lv_indev_read(indev_act, &data); continue_reading = data.continue_reading; - /*The active object might deleted even in the read function*/ + /*The active object might be deleted even in the read function*/ indev_proc_reset_query_handler(indev_act); indev_obj_act = NULL; @@ -121,9 +122,18 @@ void lv_indev_read_timer_cb(lv_timer_t * timer) void lv_indev_enable(lv_indev_t * indev, bool en) { - if(!indev) return; + uint8_t enable = en ? 0 : 1; - indev->proc.disabled = en ? 0 : 1; + if(indev) { + indev->proc.disabled = enable; + } + else { + lv_indev_t * i = lv_indev_get_next(NULL); + while(i) { + i->proc.disabled = enable; + i = lv_indev_get_next(i); + } + } } lv_indev_t * lv_indev_get_act(void) @@ -286,6 +296,7 @@ lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev) return indev->refr_timer; } + lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) { lv_obj_t * found_p = NULL; @@ -293,16 +304,20 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) /*If this obj is hidden the children are hidden too so return immediately*/ if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL; - bool hit_test_ok = lv_obj_hit_test(obj, point); + lv_point_t p_trans = *point; + lv_obj_transform_point(obj, &p_trans, false, true); + + bool hit_test_ok = lv_obj_hit_test(obj, &p_trans); /*If the point is on this object or has overflow visible check its children too*/ - if(_lv_area_is_point_on(&obj->coords, point, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { + if(_lv_area_is_point_on(&obj->coords, &p_trans, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { int32_t i; uint32_t child_cnt = lv_obj_get_child_cnt(obj); + /*If a child matches use it*/ for(i = child_cnt - 1; i >= 0; i--) { lv_obj_t * child = obj->spec_attr->children[i]; - found_p = lv_indev_search_obj(child, point); + found_p = lv_indev_search_obj(child, &p_trans); if(found_p) return found_p; } } @@ -395,6 +410,8 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) indev_obj_act = lv_group_get_focused(g); if(indev_obj_act == NULL) return; + bool dis = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + /*Save the last key to compare it with the current latter on RELEASE*/ uint32_t prev_key = i->proc.types.keypad.last_key; @@ -410,26 +427,11 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) /*Key press happened*/ if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) { - LV_LOG_INFO("%d key is pressed", data->key); + LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key); i->proc.pr_timestamp = lv_tick_get(); - /*Simulate a press on the object if ENTER was pressed*/ - if(data->key == LV_KEY_ENTER) { - /*Send the ENTER as a normal KEY*/ - lv_group_send_data(g, LV_KEY_ENTER); - - lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - else if(data->key == LV_KEY_ESC) { - /*Send the ESC as a normal KEY*/ - lv_group_send_data(g, LV_KEY_ESC); - - lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); - if(indev_reset_check(&i->proc)) return; - } /*Move the focus on NEXT*/ - else if(data->key == LV_KEY_NEXT) { + if(data->key == LV_KEY_NEXT) { lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ lv_group_focus_next(g); if(indev_reset_check(&i->proc)) return; @@ -440,13 +442,33 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) lv_group_focus_prev(g); if(indev_reset_check(&i->proc)) return; } - /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ - else { - lv_group_send_data(g, data->key); + else if(!dis) { + /*Simulate a press on the object if ENTER was pressed*/ + if(data->key == LV_KEY_ENTER) { + /*Send the ENTER as a normal KEY*/ + lv_group_send_data(g, LV_KEY_ENTER); + if(indev_reset_check(&i->proc)) return; + + if(!dis) lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); + if(indev_reset_check(&i->proc)) return; + } + else if(data->key == LV_KEY_ESC) { + /*Send the ESC as a normal KEY*/ + lv_group_send_data(g, LV_KEY_ESC); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); + if(indev_reset_check(&i->proc)) return; + } + /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ + else { + lv_group_send_data(g, data->key); + if(indev_reset_check(&i->proc)) return; + } } } /*Pressing*/ - else if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) { + else if(!dis && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) { if(data->key == LV_KEY_ENTER) { lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act); @@ -493,8 +515,8 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) } } /*Release happened*/ - else if(data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) { - LV_LOG_INFO("%d key is released", data->key); + else if(!dis && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) { + LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key); /*The user might clear the key when it was released. Always release the pressed key*/ data->key = prev_key; if(data->key == LV_KEY_ENTER) { @@ -579,6 +601,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) else if(data->key == LV_KEY_ESC) { /*Send the ESC as a normal KEY*/ lv_group_send_data(g, LV_KEY_ESC); + if(indev_reset_check(&i->proc)) return; lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); if(indev_reset_check(&i->proc)) return; @@ -586,6 +609,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ else { lv_group_send_data(g, data->key); + if(indev_reset_check(&i->proc)) return; } } /*Pressing*/ @@ -676,8 +700,8 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); if(indev_reset_check(&i->proc)) return; - lv_group_send_data(g, LV_KEY_ENTER); + if(indev_reset_check(&i->proc)) return; } else { lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ @@ -703,10 +727,16 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff); int32_t s; if(data->enc_diff < 0) { - for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(g, LV_KEY_LEFT); + for(s = 0; s < -data->enc_diff; s++) { + lv_group_send_data(g, LV_KEY_LEFT); + if(indev_reset_check(&i->proc)) return; + } } else if(data->enc_diff > 0) { - for(s = 0; s < data->enc_diff; s++) lv_group_send_data(g, LV_KEY_RIGHT); + for(s = 0; s < data->enc_diff; s++) { + lv_group_send_data(g, LV_KEY_RIGHT); + if(indev_reset_check(&i->proc)) return; + } } } /*In navigate mode focus on the next/prev objects*/ @@ -714,10 +744,16 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff); int32_t s; if(data->enc_diff < 0) { - for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(g); + for(s = 0; s < -data->enc_diff; s++) { + lv_group_focus_prev(g); + if(indev_reset_check(&i->proc)) return; + } } else if(data->enc_diff > 0) { - for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(g); + for(s = 0; s < data->enc_diff; s++) { + lv_group_focus_next(g); + if(indev_reset_check(&i->proc)) return; + } } } } @@ -743,10 +779,10 @@ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) static lv_indev_state_t prev_state = LV_INDEV_STATE_RELEASED; if(prev_state != data->state) { if(data->state == LV_INDEV_STATE_PRESSED) { - LV_LOG_INFO("button %d is pressed (x:%d y:%d)", data->btn_id, x, y); + LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, x, y); } else { - LV_LOG_INFO("button %d is released (x:%d y:%d)", data->btn_id, x, y); + LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, x, y); } } @@ -816,7 +852,9 @@ static void indev_proc_press(_lv_indev_proc_t * proc) if(indev_reset_check(proc)) return; } - /*If a new object was found reset some variables and send a pressed Call the ancestor's event handler*/ + lv_obj_transform_point(indev_obj_act, &proc->types.pointer.act_point, true, true); + + /*If a new object was found reset some variables and send a pressed event handler*/ if(indev_obj_act != proc->types.pointer.act_obj) { proc->types.pointer.last_point.x = proc->types.pointer.act_point.x; proc->types.pointer.last_point.y = proc->types.pointer.act_point.y; @@ -864,11 +902,8 @@ static void indev_proc_press(_lv_indev_proc_t * proc) proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; - proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x * 4) >> 3; - proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y * 4) >> 3; - - proc->types.pointer.scroll_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3; - proc->types.pointer.scroll_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3; + proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x + proc->types.pointer.vect.x) / 2; + proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y + proc->types.pointer.vect.y) / 2; proc->types.pointer.scroll_throw_vect_ori = proc->types.pointer.scroll_throw_vect; @@ -917,6 +952,9 @@ static void indev_proc_press(_lv_indev_proc_t * proc) static void indev_proc_release(_lv_indev_proc_t * proc) { if(proc->wait_until_release != 0) { + lv_event_send(proc->types.pointer.act_obj, LV_EVENT_PRESS_LOST, indev_act); + if(indev_reset_check(proc)) return; + proc->types.pointer.act_obj = NULL; proc->types.pointer.last_obj = NULL; proc->pr_timestamp = 0; diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h index 80c793977..a98df86ef 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h @@ -35,7 +35,11 @@ extern "C" { */ void lv_indev_read_timer_cb(lv_timer_t * timer); - +/** + * Enable or disable one or all input devices (default enabled) + * @param indev pointer to an input device or NULL to enable/disable all of them + * @param en true to enable, false to disable + */ void lv_indev_enable(lv_indev_t * indev, bool en); /** diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c b/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c index 96fa2f66d..c05e3459f 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c @@ -85,7 +85,8 @@ void _lv_indev_scroll_handler(_lv_indev_proc_t * proc) /*Respect the scroll limit area*/ scroll_limit_diff(proc, &diff_x, &diff_y); - lv_obj_scroll_by(scroll_obj, diff_x, diff_y, LV_ANIM_OFF); + _lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y); + if(proc->reset_query) return; proc->types.pointer.scroll_sum.x += diff_x; proc->types.pointer.scroll_sum.y += diff_y; } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c index 0b5f27a85..8890fcbe0 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c @@ -30,9 +30,12 @@ #include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h" #endif +#if LV_USE_GPU_SWM341_DMA2D + #include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h" +#endif + #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT - #include "../gpu/lv_gpu_nxp_pxp.h" - #include "../gpu/lv_gpu_nxp_pxp_osa.h" + #include "../draw/nxp/pxp/lv_gpu_nxp_pxp.h" #endif /********************* @@ -41,7 +44,6 @@ #define MY_CLASS &lv_obj_class #define LV_OBJ_DEF_WIDTH (LV_DPX(100)) #define LV_OBJ_DEF_HEIGHT (LV_DPX(50)) -#define GRID_DEBUG 0 /*Draw rectangles on grid cells*/ #define STYLE_TRANSITION_MAX 32 /********************** @@ -117,11 +119,13 @@ void lv_init(void) lv_draw_stm32_dma2d_init(); #endif +#if LV_USE_GPU_SWM341_DMA2D + /*Initialize DMA2D GPU*/ + lv_draw_swm341_dma2d_init(); +#endif + #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT - if(lv_gpu_nxp_pxp_init(&pxp_default_cfg) != LV_RES_OK) { - LV_LOG_ERROR("PXP init error. STOP.\n"); - for(; ;) ; - } + PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed."); #endif _lv_obj_style_init(); @@ -265,6 +269,7 @@ void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) { lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); } + } void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) @@ -489,17 +494,6 @@ static void lv_obj_draw(lv_event_t * e) return; } -#if LV_DRAW_COMPLEX - if(lv_obj_get_style_blend_mode(obj, LV_PART_MAIN) != LV_BLEND_MODE_NORMAL) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } -#endif - if(lv_obj_get_style_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - info->res = LV_COVER_RES_COVER; } @@ -531,7 +525,6 @@ static void lv_obj_draw(lv_event_t * e) part_dsc.part = LV_PART_MAIN; lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); - #if LV_DRAW_COMPLEX /*With clip corner enabled draw the bg img separately to make it clipped*/ bool clip_corner = (lv_obj_get_style_clip_corner(obj, LV_PART_MAIN) && draw_dsc.radius != 0) ? true : false; @@ -846,9 +839,8 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t * s = lv_event_get_param(e); lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN); - *s = LV_MAX(*s, d); + lv_event_set_ext_draw_size(e, d); } else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) { lv_obj_draw(e); @@ -886,7 +878,7 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) if(obj_style->is_trans) continue; lv_style_value_t v; - if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) == false) continue; + if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) != LV_STYLE_RES_FOUND) continue; const lv_style_transition_dsc_t * tr = v.ptr; /*Add the props to the set if not added yet or added but with smaller weight*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h index 7bd89c8a4..c89e46099 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h @@ -63,7 +63,7 @@ typedef uint16_t lv_state_t; * The possible parts of widgets. * The parts can be considered as the internal building block of the widgets. * E.g. slider = background + indicator + knob - * Note every part is used by every widget + * Not all parts are used by every widget */ enum { LV_PART_MAIN = 0x000000, /**< A background like rectangle*/ @@ -167,7 +167,8 @@ typedef struct { lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/ lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/ lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/ - uint8_t event_dsc_cnt; /**< Number of event callbacks stored in `event_dsc` array*/ + uint8_t event_dsc_cnt : 6; /**< Number of event callbacks stored in `event_dsc` array*/ + uint8_t layer_type : 2; /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */ } _lv_obj_spec_attr_t; typedef struct _lv_obj_t { diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c index 174453e98..fe2044824 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c @@ -56,6 +56,7 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa lv_disp_t * disp = lv_disp_get_default(); if(!disp) { LV_LOG_WARN("No display created yet. No place to assign the new screen"); + lv_mem_free(obj); return NULL; } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c index db7c6ea54..f2428cddf 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c @@ -38,21 +38,23 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc) { - -#if LV_DRAW_COMPLEX - draw_dsc->radius = lv_obj_get_style_radius(obj, part); - - lv_opa_t main_opa = part != LV_PART_MAIN ? lv_obj_get_style_opa(obj, part) : LV_OPA_COVER; - lv_opa_t opa = lv_obj_get_style_opa(obj, part); - if(opa <= LV_OPA_MIN || main_opa <= LV_OPA_MIN) { - draw_dsc->bg_opa = LV_OPA_TRANSP; - draw_dsc->border_opa = LV_OPA_TRANSP; - draw_dsc->shadow_opa = LV_OPA_TRANSP; - draw_dsc->outline_opa = LV_OPA_TRANSP; - return; + lv_opa_t opa = LV_OPA_COVER; + if(part != LV_PART_MAIN) { + opa = lv_obj_get_style_opa(obj, part); + if(opa <= LV_OPA_MIN) { + draw_dsc->bg_opa = LV_OPA_TRANSP; + draw_dsc->bg_img_opa = LV_OPA_TRANSP; + draw_dsc->border_opa = LV_OPA_TRANSP; + draw_dsc->outline_opa = LV_OPA_TRANSP; + draw_dsc->shadow_opa = LV_OPA_TRANSP; + return; + } } - draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); +#if LV_DRAW_COMPLEX + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); + + draw_dsc->radius = lv_obj_get_style_radius(obj, part); if(draw_dsc->bg_opa != LV_OPA_TRANSP) { draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part); @@ -130,17 +132,6 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } - if(main_opa < LV_OPA_MAX) { - opa = (uint16_t)((uint16_t) main_opa * opa) >> 8; - } - - if(opa < LV_OPA_MAX) { - draw_dsc->bg_opa = (uint16_t)((uint16_t)draw_dsc->bg_opa * opa) >> 8; - draw_dsc->bg_img_opa = (uint16_t)((uint16_t)draw_dsc->bg_img_opa * opa) >> 8; - draw_dsc->border_opa = (uint16_t)((uint16_t)draw_dsc->border_opa * opa) >> 8; - draw_dsc->shadow_opa = (uint16_t)((uint16_t)draw_dsc->shadow_opa * opa) >> 8; - draw_dsc->outline_opa = (uint16_t)((uint16_t)draw_dsc->outline_opa * opa) >> 8; - } #else /*LV_DRAW_COMPLEX*/ if(draw_dsc->bg_opa != LV_OPA_TRANSP) { draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part); @@ -189,6 +180,16 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } #endif + + if(part != LV_PART_MAIN) { + if(opa < LV_OPA_MAX) { + draw_dsc->bg_opa = (opa * draw_dsc->shadow_opa) >> 8; + draw_dsc->bg_img_opa = (opa * draw_dsc->shadow_opa) >> 8; + draw_dsc->border_opa = (opa * draw_dsc->shadow_opa) >> 8; + draw_dsc->outline_opa = (opa * draw_dsc->shadow_opa) >> 8; + draw_dsc->shadow_opa = (opa * draw_dsc->shadow_opa) >> 8; + } + } } void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc) @@ -196,18 +197,23 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc draw_dsc->opa = lv_obj_get_style_text_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; - lv_opa_t opa = lv_obj_get_style_opa(obj, part); - if(opa < LV_OPA_MAX) { - draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8; + if(part != LV_PART_MAIN) { + lv_opa_t opa = lv_obj_get_style_opa(obj, part); + if(opa <= LV_OPA_MIN) { + draw_dsc->opa = LV_OPA_TRANSP; + return; + } + if(opa < LV_OPA_MAX) { + draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + } } - if(draw_dsc->opa <= LV_OPA_MIN) return; draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part); draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part); draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part); draw_dsc->decor = lv_obj_get_style_text_decor(obj, part); #if LV_DRAW_COMPLEX - draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); #endif draw_dsc->font = lv_obj_get_style_text_font(obj, part); @@ -222,13 +228,18 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc) { draw_dsc->opa = lv_obj_get_style_img_opa(obj, part); - if(draw_dsc->opa <= LV_OPA_MIN) return; + if(draw_dsc->opa <= LV_OPA_MIN) return; - lv_opa_t opa_scale = lv_obj_get_style_opa(obj, part); - if(opa_scale < LV_OPA_MAX) { - draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8; + if(part != LV_PART_MAIN) { + lv_opa_t opa = lv_obj_get_style_opa(obj, part); + if(opa <= LV_OPA_MIN) { + draw_dsc->opa = LV_OPA_TRANSP; + return; + } + if(opa < LV_OPA_MAX) { + draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + } } - if(draw_dsc->opa <= LV_OPA_MIN) return; draw_dsc->angle = 0; draw_dsc->zoom = LV_IMG_ZOOM_NONE; @@ -240,23 +251,28 @@ void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part); } #if LV_DRAW_COMPLEX - draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); #endif } void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc) { - draw_dsc->width = lv_obj_get_style_line_width(obj, part); - if(draw_dsc->width == 0) return; - draw_dsc->opa = lv_obj_get_style_line_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; - lv_opa_t opa = lv_obj_get_style_opa(obj, part); - if(opa < LV_OPA_MAX) { - draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8; + if(part != LV_PART_MAIN) { + lv_opa_t opa = lv_obj_get_style_opa(obj, part); + if(opa <= LV_OPA_MIN) { + draw_dsc->opa = LV_OPA_TRANSP; + return; + } + if(opa < LV_OPA_MAX) { + draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + } } - if(draw_dsc->opa <= LV_OPA_MIN) return; + + draw_dsc->width = lv_obj_get_style_line_width(obj, part); + if(draw_dsc->width == 0) return; draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part); @@ -269,7 +285,7 @@ void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t draw_dsc->round_end = draw_dsc->round_start; #if LV_DRAW_COMPLEX - draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); #endif } @@ -281,11 +297,16 @@ void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; - lv_opa_t opa = lv_obj_get_style_opa(obj, part); - if(opa < LV_OPA_MAX) { - draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8; + if(part != LV_PART_MAIN) { + lv_opa_t opa = lv_obj_get_style_opa(obj, part); + if(opa <= LV_OPA_MIN) { + draw_dsc->opa = LV_OPA_TRANSP; + return; + } + if(opa < LV_OPA_MAX) { + draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + } } - if(draw_dsc->opa <= LV_OPA_MIN) return; draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part); draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part); @@ -293,7 +314,7 @@ void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part); #if LV_DRAW_COMPLEX - draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); #endif } @@ -373,6 +394,13 @@ lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj) else return 0; } +lv_layer_type_t _lv_obj_get_layer_type(const lv_obj_t * obj) +{ + + if(obj->spec_attr) return obj->spec_attr->layer_type; + else return LV_LAYER_TYPE_NONE; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h index 063216540..3f9d0f30f 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h @@ -33,6 +33,12 @@ typedef enum { LV_COVER_RES_MASKED = 2, } lv_cover_res_t; +typedef enum { + LV_LAYER_TYPE_NONE, + LV_LAYER_TYPE_SIMPLE, + LV_LAYER_TYPE_TRANSFORM, +} lv_layer_type_t; + typedef struct { lv_draw_ctx_t * draw_ctx; /**< Draw context*/ const struct _lv_obj_class_t * class_p; /**< The class that sent the event */ @@ -50,14 +56,14 @@ typedef struct { arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/ const lv_point_t * p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/ - const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/ + const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/ char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/ - uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/ - uint32_t part; /**< The current part for which the event is sent*/ - uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/ - lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/ - int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/ - const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */ + uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/ + uint32_t part; /**< The current part for which the event is sent*/ + uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/ + lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/ + int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/ + const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */ } lv_obj_draw_part_dsc_t; /********************** @@ -66,11 +72,11 @@ typedef struct { /** * Initialize a rectangle draw descriptor from an object's styles in its current state - * @param obj pointer to an object - * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor to initialize. - * If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized. - * Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`. + * @param obj pointer to an object + * @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized. + * Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`. * @note Only the relevant fields will be set. * E.g. if `border width == 0` the other border properties won't be evaluated. */ @@ -78,20 +84,20 @@ void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_re /** * Initialize a label draw descriptor from an object's styles in its current state - * @param obj pointer to an object - * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor to initialize. - * If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. - * Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`. + * @param obj pointer to an object + * @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. + * Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc); /** * Initialize an image draw descriptor from an object's styles in its current state - * @param obj pointer to an object - * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor to initialize. - * Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`. + * @param obj pointer to an object + * @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc); @@ -99,33 +105,33 @@ void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img /** * Initialize a line draw descriptor from an object's styles in its current state * @param obj pointer to an object - * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor to initialize. - * Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`. + * @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc); /** * Initialize an arc draw descriptor from an object's styles in its current state - * @param obj pointer to an object - * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc - * @param draw_dsc the descriptor to initialize. - * Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`. + * @param obj pointer to an object + * @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`. */ void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc); /** * Get the required extra size (around the object's part) to draw shadow, outline, value etc. - * @param obj pointer to an object - * @param part part of the object - * @return the extra size required around the object + * @param obj pointer to an object + * @param part part of the object + * @return the extra size required around the object */ lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part); /** * Initialize a draw descriptor used in events. - * @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EEVNT_DRAW_PART_BEGIN/END` event. - * @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`) + * @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EVENT_DRAW_PART_BEGIN/END` event. + * @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`) */ void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx); @@ -141,17 +147,20 @@ bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_ /** * Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size. * The result will be saved in `obj`. - * @param obj pointer to an object + * @param obj pointer to an object */ void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj); /** * Get the extended draw area of an object. - * @param obj pointer to an object - * @return the size extended draw area around the real coordinates + * @param obj pointer to an object + * @return the size extended draw area around the real coordinates */ lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj); + +lv_layer_type_t _lv_obj_get_layer_type(const struct _lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c index 92d4bc4d9..a31c11db8 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c @@ -26,6 +26,7 @@ static lv_coord_t calc_content_width(lv_obj_t * obj); static lv_coord_t calc_content_height(lv_obj_t * obj); static void layout_update_core(lv_obj_t * obj); +static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv); /********************** * STATIC VARIABLES @@ -206,6 +207,8 @@ bool lv_obj_refr_size(lv_obj_t * obj) bool on2 = _lv_area_is_in(&obj->coords, &parent_fit_area, 0); if(on1 || (!on1 && on2)) lv_obj_scrollbar_invalidate(parent); + lv_obj_refresh_ext_draw_size(obj); + return true; } @@ -627,6 +630,7 @@ void lv_obj_refr_pos(lv_obj_t * obj) { if(lv_obj_is_layout_positioned(obj)) return; + lv_obj_t * parent = lv_obj_get_parent(obj); lv_coord_t x = lv_obj_get_style_x(obj, LV_PART_MAIN); lv_coord_t y = lv_obj_get_style_y(obj, LV_PART_MAIN); @@ -791,28 +795,63 @@ void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_dif } } +void lv_obj_transform_point(const lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv) +{ + if(obj) { + lv_layer_type_t layer_type = _lv_obj_get_layer_type(obj); + bool do_tranf = layer_type == LV_LAYER_TYPE_TRANSFORM; + if(inv) { + if(recursive) lv_obj_transform_point(lv_obj_get_parent(obj), p, recursive, inv); + if(do_tranf) transform_point(obj, p, inv); + } + else { + if(do_tranf) transform_point(obj, p, inv); + if(recursive) lv_obj_transform_point(lv_obj_get_parent(obj), p, recursive, inv); + } + } +} + +void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, bool recursive, + bool inv) +{ + lv_point_t p[4] = { + {area->x1, area->y1}, + {area->x1, area->y2}, + {area->x2, area->y1}, + {area->x2, area->y2}, + }; + + lv_obj_transform_point(obj, &p[0], recursive, inv); + lv_obj_transform_point(obj, &p[1], recursive, inv); + lv_obj_transform_point(obj, &p[2], recursive, inv); + lv_obj_transform_point(obj, &p[3], recursive, inv); + + area->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x); + area->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x); + area->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y); + area->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y); + lv_area_increase(area, 5, 5); +} + void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) { LV_ASSERT_OBJ(obj, MY_CLASS); + lv_disp_t * disp = lv_obj_get_disp(obj); + if(!lv_disp_is_invalidation_enabled(disp)) return; + lv_area_t area_tmp; lv_area_copy(&area_tmp, area); - bool visible = lv_obj_area_is_visible(obj, &area_tmp); + if(!lv_obj_area_is_visible(obj, &area_tmp)) return; - if(visible) _lv_inv_area(lv_obj_get_disp(obj), &area_tmp); + _lv_inv_area(lv_obj_get_disp(obj), &area_tmp); } void lv_obj_invalidate(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - /*If the object has overflow visible it can be drawn anywhere on its parent - *It needs to be checked recursively*/ - while(lv_obj_get_parent(obj) && lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - obj = lv_obj_get_parent(obj); - } - /*Truncate the area to the object*/ lv_area_t obj_coords; lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); @@ -841,7 +880,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) } /*Truncate the area to the object*/ - if(!lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { + if(!lv_obj_has_flag_any(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { lv_area_t obj_coords; lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_area_copy(&obj_coords, &obj->coords); @@ -854,6 +893,9 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) if(!_lv_area_intersect(area, area, &obj_coords)) return false; } + lv_obj_get_transformed_area(obj, area, true, false); + + /*Truncate recursively to the parents*/ lv_obj_t * par = lv_obj_get_parent(obj); while(par != NULL) { @@ -861,8 +903,10 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; /*Truncate to the parent and if no common parts break*/ - if(!lv_obj_has_flag(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - if(!_lv_area_intersect(area, area, &par->coords)) return false; + if(!lv_obj_has_flag_any(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { + lv_area_t par_area = par->coords; + lv_obj_get_transformed_area(par, &par_area, true, false); + if(!_lv_area_intersect(area, area, &par_area)) return false; } par = lv_obj_get_parent(par); @@ -1108,3 +1152,21 @@ static void layout_update_core(lv_obj_t * obj) } } } + +static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv) +{ + int16_t angle = lv_obj_get_style_transform_angle(obj, 0); + int16_t zoom = lv_obj_get_style_transform_zoom(obj, 0); + + if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) return; + + lv_point_t pivot; + pivot.x = obj->coords.x1 + lv_obj_get_style_transform_pivot_x(obj, 0); + pivot.y = obj->coords.y1 + lv_obj_get_style_transform_pivot_y(obj, 0); + if(inv) { + angle = -angle; + zoom = (256 * 256) / zoom; + } + + lv_point_transform(p, angle, zoom, &pivot); +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h index 60130398e..d20ee9656 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h @@ -348,6 +348,24 @@ void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating); +/** + * Transform a point using the angle and zoom style properties of an object + * @param obj pointer to an object whose style properties should be used + * @param p a point to transform, the result will be written back here too + * @param recursive consider the transformation properties of the parents too + * @param inv do the inverse of the transformation (-angle and 1/zoom) + */ +void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv); + +/** + * Transform an area using the angle and zoom style properties of an object + * @param obj pointer to an object whose style properties should be used + * @param area an area to transform, the result will be written back here too + * @param recursive consider the transformation properties of the parents too + * @param inv do the inverse of the transformation (-angle and 1/zoom) + */ +void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv); + /** * Mark an area of an object as invalid. * The area will be truncated to the object's area and marked for redraw. diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c index 6927acace..02b982614 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c @@ -31,7 +31,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static void scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); static void scroll_x_anim(void * obj, int32_t v); static void scroll_y_anim(void * obj, int32_t v); static void scroll_anim_ready_cb(lv_anim_t * a); @@ -345,14 +344,18 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enab } else { /*Remove pending animations*/ - bool y_del = lv_anim_del(obj, scroll_y_anim); - bool x_del = lv_anim_del(obj, scroll_x_anim); - scroll_by_raw(obj, dx, dy); - if(y_del || x_del) { - lv_res_t res; - res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL); - if(res != LV_RES_OK) return; - } + lv_anim_del(obj, scroll_y_anim); + lv_anim_del(obj, scroll_x_anim); + + lv_res_t res; + res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, NULL); + if(res != LV_RES_OK) return; + + res = _lv_obj_scroll_by_raw(obj, dx, dy); + if(res != LV_RES_OK) return; + + res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL); + if(res != LV_RES_OK) return; } } @@ -406,6 +409,23 @@ void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en) } } +lv_res_t _lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +{ + if(x == 0 && y == 0) return LV_RES_OK; + + lv_obj_allocate_spec_attr(obj); + + obj->spec_attr->scroll.x += x; + obj->spec_attr->scroll.y += y; + + lv_obj_move_children_by(obj, x, y, true); + lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL); + if(res != LV_RES_OK) return res; + lv_obj_invalidate(obj); + return LV_RES_OK; +} + + bool lv_obj_is_scrolling(const lv_obj_t * obj) { lv_indev_t * indev = lv_indev_get_next(NULL); @@ -648,29 +668,15 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) * STATIC FUNCTIONS **********************/ -static void scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -{ - if(x == 0 && y == 0) return; - - lv_obj_allocate_spec_attr(obj); - - obj->spec_attr->scroll.x += x; - obj->spec_attr->scroll.y += y; - - lv_obj_move_children_by(obj, x, y, true); - lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL); - if(res != LV_RES_OK) return; - lv_obj_invalidate(obj); -} static void scroll_x_anim(void * obj, int32_t v) { - scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0); + _lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0); } static void scroll_y_anim(void * obj, int32_t v) { - scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj)); + _lv_obj_scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj)); } static void scroll_anim_ready_cb(lv_anim_t * a) @@ -746,7 +752,7 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p x_scroll = left_diff; /*Do not let scrolling in*/ lv_coord_t sl = lv_obj_get_scroll_left(parent); - if(sl + x_scroll > 0) x_scroll = 0; + if(sl - x_scroll < 0) x_scroll = 0; } else if(right_diff > 0) { x_scroll = -right_diff; diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h index c9fdd720d..e1da245b7 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h @@ -15,6 +15,7 @@ extern "C" { *********************/ #include "../misc/lv_area.h" #include "../misc/lv_anim.h" +#include "../misc/lv_types.h" /********************* * DEFINES @@ -248,6 +249,18 @@ void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); */ void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); + +/** + * Low level function to scroll by given x and y coordinates. + * `LV_EVENT_SCROLL` is sent. + * @param obj pointer to an object to scroll + * @param x pixels to scroll horizontally + * @param y pixels to scroll vertically + * @return `LV_RES_INV`: to object was deleted in `LV_EVENT_SCROLL`; + * `LV_RES_OK`: if the object is still valid + */ +lv_res_t _lv_obj_scroll_by_raw(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); + /** * Tell whether an object is being scrolled or not at this moment * @param obj pointer to an object diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c index 82e1ebba2..86016c415 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c @@ -44,14 +44,14 @@ typedef enum { **********************/ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector); static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part); -static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v); -static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v); +static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v); static void report_style_change_core(void * style, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit); static void trans_anim_cb(void * _tr, int32_t v); static void trans_anim_start_cb(lv_anim_t * a); static void trans_anim_ready_cb(lv_anim_t * a); +static lv_layer_type_t calculate_layer_type(lv_obj_t * obj); static void fade_anim_cb(void * obj, int32_t v); static void fade_in_anim_ready(lv_anim_t * a); @@ -174,7 +174,12 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style lv_part_t part = lv_obj_style_get_selector_part(selector); - if(prop & LV_STYLE_PROP_LAYOUT_REFR) { + bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYOUT_REFR); + bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_EXT_DRAW); + bool is_inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT); + bool is_layer_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYER_REFR); + + if(is_layout_refr) { if(part == LV_PART_ANY || part == LV_PART_MAIN || lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT || @@ -183,19 +188,27 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style lv_obj_mark_layout_as_dirty(obj); } } - if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || - (prop & LV_STYLE_PROP_PARENT_LAYOUT_REFR))) { + if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || is_layout_refr)) { lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) lv_obj_mark_layout_as_dirty(parent); } - if(prop == LV_STYLE_PROP_ANY || (prop & LV_STYLE_PROP_EXT_DRAW)) { + /*Cache the layer type*/ + if((part == LV_PART_ANY || part == LV_PART_MAIN) && is_layer_refr) { + lv_layer_type_t layer_type = calculate_layer_type(obj); + if(obj->spec_attr) obj->spec_attr->layer_type = layer_type; + else if(layer_type != LV_LAYER_TYPE_NONE) { + lv_obj_allocate_spec_attr(obj); + obj->spec_attr->layer_type = layer_type; + } + } + + if(prop == LV_STYLE_PROP_ANY || is_ext_draw) { lv_obj_refresh_ext_draw_size(obj); } lv_obj_invalidate(obj); - if(prop == LV_STYLE_PROP_ANY || - ((prop & LV_STYLE_PROP_INHERIT) && ((prop & LV_STYLE_PROP_EXT_DRAW) || (prop & LV_STYLE_PROP_LAYOUT_REFR)))) { + if(prop == LV_STYLE_PROP_ANY || (is_inheritable && (is_ext_draw || is_layout_refr))) { if(part != LV_PART_SCROLLBAR) { refresh_children_style(obj); } @@ -210,19 +223,15 @@ void lv_obj_enable_style_refresh(bool en) lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) { lv_style_value_t value_act; - bool inherit = prop & LV_STYLE_PROP_INHERIT ? true : false; - bool filter = prop & LV_STYLE_PROP_FILTER ? true : false; - if(filter) { - prop &= ~LV_STYLE_PROP_FILTER; - } - bool found = false; + bool inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT); + lv_style_res_t found = LV_STYLE_RES_NOT_FOUND; while(obj) { found = get_prop_core(obj, part, prop, &value_act); - if(found) break; - if(!inherit) break; + if(found == LV_STYLE_RES_FOUND) break; + if(!inheritable) break; /*If not found, check the `MAIN` style first*/ - if(part != LV_PART_MAIN) { + if(found != LV_STYLE_RES_INHERIT && part != LV_PART_MAIN) { part = LV_PART_MAIN; continue; } @@ -231,7 +240,7 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_ obj = lv_obj_get_parent(obj); } - if(!found) { + if(found != LV_STYLE_RES_FOUND) { if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) { const lv_obj_class_t * cls = obj->class_p; while(cls) { @@ -244,13 +253,17 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_ cls = cls->base_class; } - value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def; + if(cls) { + value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def; + } + else { + value_act.num = 0; + } } else { value_act = lv_style_prop_get_default(prop); } } - if(filter) value_act = apply_color_filter(obj, part, value_act); return value_act; } @@ -262,9 +275,17 @@ void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_ lv_obj_refresh_style(obj, selector, prop); } +void lv_obj_set_local_style_prop_meta(lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, + lv_style_selector_t selector) +{ + lv_style_t * style = get_local_style(obj, selector); + lv_style_set_prop_meta(style, prop, meta); + lv_obj_refresh_style(obj, selector, prop); +} -lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, - lv_style_selector_t selector) + +lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, + lv_style_selector_t selector) { uint32_t i; for(i = 0; i < obj->style_cnt; i++) { @@ -274,7 +295,7 @@ lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_st } } - return LV_RES_INV; + return LV_STYLE_RES_NOT_FOUND; } bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector) @@ -320,7 +341,7 @@ void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t if(tr_dsc->prop == LV_STYLE_RADIUS) { if(v1.num == LV_RADIUS_CIRCLE || v2.num == LV_RADIUS_CIRCLE) { lv_coord_t whalf = lv_obj_get_width(obj) / 2; - lv_coord_t hhalf = lv_obj_get_width(obj) / 2; + lv_coord_t hhalf = lv_obj_get_height(obj) / 2; if(v1.num == LV_RADIUS_CIRCLE) v1.num = LV_MIN(whalf + 1, hhalf + 1); if(v2.num == LV_RADIUS_CIRCLE) v2.num = LV_MIN(whalf + 1, hhalf + 1); } @@ -331,28 +352,37 @@ void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t if(tr == NULL) return; tr->start_value = v1; tr->end_value = v2; + tr->obj = obj; + tr->prop = tr_dsc->prop; + tr->selector = part; - if(tr) { - tr->obj = obj; - tr->prop = tr_dsc->prop; - tr->selector = part; - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, tr); - lv_anim_set_exec_cb(&a, trans_anim_cb); - lv_anim_set_start_cb(&a, trans_anim_start_cb); - lv_anim_set_ready_cb(&a, trans_anim_ready_cb); - lv_anim_set_values(&a, 0x00, 0xFF); - lv_anim_set_time(&a, tr_dsc->time); - lv_anim_set_delay(&a, tr_dsc->delay); - lv_anim_set_path_cb(&a, tr_dsc->path_cb); - lv_anim_set_early_apply(&a, false); + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, tr); + lv_anim_set_exec_cb(&a, trans_anim_cb); + lv_anim_set_start_cb(&a, trans_anim_start_cb); + lv_anim_set_ready_cb(&a, trans_anim_ready_cb); + lv_anim_set_values(&a, 0x00, 0xFF); + lv_anim_set_time(&a, tr_dsc->time); + lv_anim_set_delay(&a, tr_dsc->delay); + lv_anim_set_path_cb(&a, tr_dsc->path_cb); + lv_anim_set_early_apply(&a, false); #if LV_USE_USER_DATA - a.user_data = tr_dsc->user_data; + a.user_data = tr_dsc->user_data; #endif - lv_anim_start(&a); + lv_anim_start(&a); +} + + +lv_style_value_t _lv_obj_style_apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v) +{ + if(obj == NULL) return v; + const lv_color_filter_dsc_t * f = lv_obj_get_style_color_filter_dsc(obj, part); + if(f && f->filter_cb) { + lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part); + if(f_opa != 0) v.color = f->filter_cb(f, v.color, f_opa); } + return v; } _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2) @@ -534,7 +564,7 @@ static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t se } -static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v) +static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v) { uint8_t group = 1 << _lv_style_get_prop_group(prop); int32_t weight = -1; @@ -543,7 +573,7 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t lv_style_value_t value_tmp; bool skip_trans = obj->skip_trans; uint32_t i; - bool found; + lv_style_res_t found; for(i = 0; i < obj->style_cnt; i++) { _lv_obj_style_t * obj_style = &obj->styles[i]; if(obj_style->is_trans == false) break; @@ -554,20 +584,22 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t if(part_act != part) continue; if((obj_style->style->has_group & group) == 0) continue; found = lv_style_get_prop(obj_style->style, prop, &value_tmp); - if(found) { + if(found == LV_STYLE_RES_FOUND) { *v = value_tmp; - return true; + return LV_STYLE_RES_FOUND; + } + else if(found == LV_STYLE_RES_INHERIT) { + return LV_STYLE_RES_INHERIT; } } for(; i < obj->style_cnt; i++) { + if((obj->styles[i].style->has_group & group) == 0) continue; _lv_obj_style_t * obj_style = &obj->styles[i]; lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector); lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector); if(part_act != part) continue; - if((obj_style->style->has_group & group) == 0) continue; - /*Be sure the style not specifies other state than the requested. *E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/ if((state_act & state_inv)) continue; @@ -577,34 +609,26 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t found = lv_style_get_prop(obj_style->style, prop, &value_tmp); - if(found) { + if(found == LV_STYLE_RES_FOUND) { if(state_act == state) { *v = value_tmp; - return true; + return LV_STYLE_RES_FOUND; } if(weight < state_act) { weight = state_act; *v = value_tmp; } } + else if(found == LV_STYLE_RES_INHERIT) { + return LV_STYLE_RES_INHERIT; + } } if(weight >= 0) { *v = value_tmp; - return true; + return LV_STYLE_RES_FOUND; } - else return false; -} - -static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v) -{ - if(obj == NULL) return v; - const lv_color_filter_dsc_t * f = lv_obj_get_style_color_filter_dsc(obj, part); - if(f && f->filter_cb) { - lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part); - if(f_opa != 0) v.color = f->filter_cb(f, v.color, f_opa); - } - return v; + else return LV_STYLE_RES_NOT_FOUND; } /** @@ -669,19 +693,21 @@ static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, tran tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); if(tr->obj == obj && (part == tr->selector || part == LV_PART_ANY) && (prop == tr->prop || prop == LV_STYLE_PROP_ANY)) { - /*Remove the transitioned property from trans. style + /*Remove any transitioned properties from the trans. style *to allow changing it by normal styles*/ uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_trans && (part == LV_PART_ANY || obj->styles[i].selector == part)) { lv_style_remove_prop(obj->styles[i].style, tr->prop); - lv_anim_del(tr, NULL); - _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); - lv_mem_free(tr); - removed = true; } } + /*Free the transition descriptor too*/ + lv_anim_del(tr, NULL); + _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); + lv_mem_free(tr); + removed = true; + } tr = tr_prev; } @@ -810,6 +836,18 @@ static void trans_anim_ready_cb(lv_anim_t * a) } } +static lv_layer_type_t calculate_layer_type(lv_obj_t * obj) +{ + if(lv_obj_get_style_transform_angle(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_zoom(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_opa(obj, 0) != LV_OPA_COVER) return LV_LAYER_TYPE_SIMPLE; + +#if LV_DRAW_COMPLEX + if(lv_obj_get_style_blend_mode(obj, 0) != LV_BLEND_MODE_NORMAL) return LV_LAYER_TYPE_SIMPLE; +#endif + return LV_LAYER_TYPE_NONE; +} + static void fade_anim_cb(void * obj, int32_t v) { lv_obj_set_style_opa(obj, v, 0); diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h index 7fb2723c8..5d122ca62 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h @@ -140,8 +140,11 @@ lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t p void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector); -lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, - lv_style_selector_t selector); +void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, + lv_style_selector_t selector); + +lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, + lv_style_selector_t selector); /** * Remove a local style property from a part of an object with a given state. @@ -152,6 +155,11 @@ lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t pro */ bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector); +/** + * Used internally for color filtering + */ +lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, uint32_t part, lv_style_value_t v); + /** * Used internally to create a style transition * @param obj diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c index 8eb7ebe6d..64a0bb28c 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c @@ -120,6 +120,22 @@ void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ANGLE, v, selector); } +void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_X, v, selector); +} + +void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_Y, v, selector); +} + void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -176,14 +192,6 @@ void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector); } -void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -200,14 +208,6 @@ void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector); } -void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -272,14 +272,6 @@ void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, l lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR, v, selector); } -void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_FILTERED, v, selector); -} - void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -304,14 +296,6 @@ void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector); } -void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -360,14 +344,6 @@ void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector); } -void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -424,14 +400,6 @@ void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector); } -void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -456,14 +424,6 @@ void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_s lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR, v, selector); } -void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_FILTERED, v, selector); -} - void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -512,14 +472,6 @@ void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector); } -void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -552,14 +504,6 @@ void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector); } -void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -584,14 +528,6 @@ void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector); } -void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .color = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR_FILTERED, v, selector); -} - void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -664,8 +600,7 @@ void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selec lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, selector); } -void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, - lv_style_selector_t selector) +void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -681,6 +616,14 @@ void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, l lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_OPA, v, selector); } +void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM, v, selector); +} + void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) { lv_style_value_t v = { @@ -697,8 +640,7 @@ void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector); } -void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, - lv_style_selector_t selector) +void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h index e4383d5ce..576927d9a 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h @@ -88,6 +88,18 @@ static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t return (lv_coord_t)v.num; } +static inline lv_coord_t lv_obj_get_style_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_X); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_Y); + return (lv_coord_t)v.num; +} + static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP); @@ -132,7 +144,7 @@ static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR)); return v.color; } @@ -150,7 +162,7 @@ static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR)); return v.color; } @@ -204,7 +216,7 @@ static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR)); return v.color; } @@ -228,7 +240,7 @@ static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR)); return v.color; } @@ -270,7 +282,7 @@ static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR)); return v.color; } @@ -318,7 +330,7 @@ static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR)); return v.color; } @@ -342,7 +354,7 @@ static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * o static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR)); return v.color; } @@ -384,7 +396,7 @@ static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * ob static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR)); return v.color; } @@ -414,7 +426,7 @@ static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR)); return v.color; } @@ -438,7 +450,7 @@ static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * ob static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR_FILTERED); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR)); return v.color; } @@ -496,8 +508,7 @@ static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32 return (lv_opa_t)v.num; } -static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, - uint32_t part) +static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC); return (const lv_color_filter_dsc_t *)v.ptr; @@ -509,6 +520,12 @@ static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t return (lv_opa_t)v.num; } +static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM); + return (const lv_anim_t *)v.ptr; +} + static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME); @@ -560,6 +577,8 @@ void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_s void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); @@ -567,10 +586,8 @@ void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_sty void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); @@ -579,18 +596,15 @@ void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t va void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector); void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); @@ -598,27 +612,22 @@ void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_ void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector); void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); @@ -628,13 +637,12 @@ void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, - lv_style_selector_t selector); +void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector); void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector); void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); -void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, - lv_style_selector_t selector); +void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector); void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector); void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c index cf82553d6..d3ad16ae3 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c @@ -65,6 +65,7 @@ void lv_obj_del(lv_obj_t * obj) /*Call the ancestor's event handler to the parent to notify it about the child delete*/ if(par) { + lv_obj_update_layout(par); lv_obj_readjust_scroll(par, LV_ANIM_OFF); lv_obj_scrollbar_invalidate(par); lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL); diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c index b9b569f90..37a437e46 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c @@ -17,6 +17,7 @@ #include "../misc/lv_gc.h" #include "../draw/lv_draw.h" #include "../font/lv_font_fmt_txt.h" +#include "../extra/others/snapshot/lv_snapshot.h" #if LV_USE_PERF_MONITOR || LV_USE_MEM_MONITOR #include "../widgets/lv_label.h" @@ -51,11 +52,12 @@ typedef struct { * STATIC PROTOTYPES **********************/ static void lv_refr_join_area(void); -static void lv_refr_areas(void); -static void lv_refr_area(const lv_area_t * area_p); -static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx); +static void refr_invalid_areas(void); +static void refr_area(const lv_area_t * area_p); +static void refr_area_part(lv_draw_ctx_t * draw_ctx); static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj); -static void lv_refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj); +static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj); +static void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area_h); static void draw_buf_flush(lv_disp_t * disp); static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p); @@ -124,11 +126,8 @@ void lv_refr_now(lv_disp_t * disp) } } -void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) { - /*Do not refresh hidden objects*/ - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; lv_area_t clip_coords_for_obj; @@ -137,31 +136,33 @@ void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) lv_obj_get_coords(obj, &obj_coords_ext); lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size); - if(!_lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &obj_coords_ext)) return; - - draw_ctx->clip_area = &clip_coords_for_obj; - - /*Draw the object*/ - lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_MAIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, draw_ctx); + bool com_clip_res = _lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &obj_coords_ext); + /*If the object is visible on the current clip area OR has overflow visible draw it. + *With overflow visible drawing should happen to apply the masks which might affect children */ + bool should_draw = com_clip_res || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE); + if(should_draw) { + draw_ctx->clip_area = &clip_coords_for_obj; + lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, draw_ctx); + lv_event_send(obj, LV_EVENT_DRAW_MAIN, draw_ctx); + lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, draw_ctx); #if LV_USE_REFR_DEBUG - lv_color_t debug_color = lv_color_make(lv_rand(0, 0xFF), lv_rand(0, 0xFF), lv_rand(0, 0xFF)); - lv_draw_rect_dsc_t draw_dsc; - lv_draw_rect_dsc_init(&draw_dsc); - draw_dsc.bg_color.full = debug_color.full; - draw_dsc.bg_opa = LV_OPA_20; - draw_dsc.border_width = 1; - draw_dsc.border_opa = LV_OPA_30; - draw_dsc.border_color = debug_color; - lv_draw_rect(draw_ctx, &draw_dsc, &obj_coords_ext); + lv_color_t debug_color = lv_color_make(lv_rand(0, 0xFF), lv_rand(0, 0xFF), lv_rand(0, 0xFF)); + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + draw_dsc.bg_color.full = debug_color.full; + draw_dsc.bg_opa = LV_OPA_20; + draw_dsc.border_width = 1; + draw_dsc.border_opa = LV_OPA_30; + draw_dsc.border_color = debug_color; + lv_draw_rect(draw_ctx, &draw_dsc, &obj_coords_ext); #endif + } /*With overflow visible keep the previous clip area to let the children visible out of this object too *With not overflow visible limit the clip are to the object's coordinates to clip the children*/ - bool refr_children = true; lv_area_t clip_coords_for_children; + bool refr_children = true; if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { clip_coords_for_children = *clip_area_ori; } @@ -177,20 +178,24 @@ void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) uint32_t child_cnt = lv_obj_get_child_cnt(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; - lv_refr_obj(draw_ctx, child); + refr_obj(draw_ctx, child); } } - draw_ctx->clip_area = &clip_coords_for_obj; + /*If the object was visible on the clip area call the post draw events too*/ + if(should_draw) { + draw_ctx->clip_area = &clip_coords_for_obj; - /*If all the children are redrawn make 'post draw' draw*/ - lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_POST, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_POST_END, draw_ctx); + /*If all the children are redrawn make 'post draw' draw*/ + lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, draw_ctx); + lv_event_send(obj, LV_EVENT_DRAW_POST, draw_ctx); + lv_event_send(obj, LV_EVENT_DRAW_POST_END, draw_ctx); + } draw_ctx->clip_area = clip_area_ori; } + /** * Invalidate an area on display to redraw it * @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas) @@ -201,6 +206,12 @@ void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) { if(!disp) disp = lv_disp_get_default(); if(!disp) return; + if(!lv_disp_is_invalidation_enabled(disp)) return; + + if(disp->rendering_in_progress) { + LV_LOG_ERROR("detected modifying dirty areas in render"); + return; + } /*Clear the invalidate buffer if the parameter is NULL*/ if(area_p == NULL) { @@ -310,7 +321,8 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) lv_refr_join_area(); - lv_refr_areas(); + refr_invalid_areas(); + /*If refresh happened ...*/ if(disp_refr->inv_p != 0) { @@ -327,6 +339,7 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) disp_refr->inv_p = 0; elaps = lv_tick_elaps(start); + /*Call monitor cb if present*/ if(disp_refr->driver->monitor_cb) { disp_refr->driver->monitor_cb(disp_refr->driver, elaps, px_num); @@ -365,9 +378,16 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) } else { perf_monitor.perf_last_time = lv_tick_get(); - uint32_t fps_limit = 1000 / disp_refr->refr_timer->period; + uint32_t fps_limit; uint32_t fps; + if(disp_refr->refr_timer) { + fps_limit = 1000 / disp_refr->refr_timer->period; + } + else { + fps_limit = 1000 / LV_DISP_DEF_REFR_PERIOD; + } + if(perf_monitor.elaps_sum == 0) { perf_monitor.elaps_sum = 1; } @@ -413,8 +433,10 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) uint32_t used_size = mon.total_size - mon.free_size;; uint32_t used_kb = used_size / 1024; uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; - lv_label_set_text_fmt(mem_label, "%" LV_PRIu32 ".%" LV_PRIu32 " kB used (%d %%)\n" \ - "%d%% frag.", used_kb, used_kb_tenth, mon.used_pct, + lv_label_set_text_fmt(mem_label, + "%"LV_PRIu32 ".%"LV_PRIu32 " kB used (%d %%)\n" + "%d%% frag.", + used_kb, used_kb_tenth, mon.used_pct, mon.frag_pct); } #endif @@ -483,7 +505,7 @@ static void lv_refr_join_area(void) /** * Refresh the joined areas */ -static void lv_refr_areas(void) +static void refr_invalid_areas(void) { px_num = 0; @@ -499,8 +521,14 @@ static void lv_refr_areas(void) } } + /*Notify the display driven rendering has started*/ + if(disp_refr->driver->render_start_cb) { + disp_refr->driver->render_start_cb(disp_refr->driver); + } + disp_refr->driver->draw_buf->last_area = 0; disp_refr->driver->draw_buf->last_part = 0; + disp_refr->rendering_in_progress = true; for(i = 0; i < disp_refr->inv_p; i++) { /*Refresh the unjoined areas*/ @@ -508,18 +536,20 @@ static void lv_refr_areas(void) if(i == last_i) disp_refr->driver->draw_buf->last_area = 1; disp_refr->driver->draw_buf->last_part = 0; - lv_refr_area(&disp_refr->inv_areas[i]); + refr_area(&disp_refr->inv_areas[i]); px_num += lv_area_get_size(&disp_refr->inv_areas[i]); } } + + disp_refr->rendering_in_progress = false; } /** * Refresh an area if there is Virtual Display Buffer * @param area_p pointer to an area to refresh */ -static void lv_refr_area(const lv_area_t * area_p) +static void refr_area(const lv_area_t * area_p) { lv_draw_ctx_t * draw_ctx = disp_refr->driver->draw_ctx; draw_ctx->buf = disp_refr->driver->draw_buf->buf_act; @@ -534,12 +564,12 @@ static void lv_refr_area(const lv_area_t * area_p) if(disp_refr->driver->full_refresh) { disp_refr->driver->draw_buf->last_part = 1; draw_ctx->clip_area = &disp_area; - lv_refr_area_part(draw_ctx); + refr_area_part(draw_ctx); } else { disp_refr->driver->draw_buf->last_part = disp_refr->driver->draw_buf->last_area; draw_ctx->clip_area = area_p; - lv_refr_area_part(draw_ctx); + refr_area_part(draw_ctx); } return; } @@ -568,7 +598,7 @@ static void lv_refr_area(const lv_area_t * area_p) if(sub_area.y2 > y2) sub_area.y2 = y2; row_last = sub_area.y2; if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; - lv_refr_area_part(draw_ctx); + refr_area_part(draw_ctx); } /*If the last y coordinates are not handled yet ...*/ @@ -582,11 +612,11 @@ static void lv_refr_area(const lv_area_t * area_p) draw_ctx->clip_area = &sub_area; draw_ctx->buf = disp_refr->driver->draw_buf->buf_act; disp_refr->driver->draw_buf->last_part = 1; - lv_refr_area_part(draw_ctx); + refr_area_part(draw_ctx); } } -static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx) +static void refr_area_part(lv_draw_ctx_t * draw_ctx) { lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); @@ -596,6 +626,18 @@ static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx) while(draw_buf->flushing) { if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); } + + /*If the screen is transparent initialize it when the flushing is ready*/ +#if LV_COLOR_SCREEN_TRANSP + if(disp_refr->driver->screen_transp) { + if(disp_refr->driver->clear_cb) { + disp_refr->driver->clear_cb(disp_refr->driver, disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size); + } + else { + lv_memset_00(disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size * LV_IMG_PX_SIZE_ALPHA_BYTE); + } + } +#endif } lv_obj_t * top_act_scr = NULL; @@ -609,6 +651,9 @@ static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx) /*Draw a display background if there is no top object*/ if(top_act_scr == NULL && top_prev_scr == NULL) { + lv_area_t a; + lv_area_set(&a, 0, 0, + lv_disp_get_hor_res(disp_refr) - 1, lv_disp_get_ver_res(disp_refr) - 1); if(draw_ctx->draw_bg) { lv_draw_rect_dsc_t dsc; lv_draw_rect_dsc_init(&dsc); @@ -616,15 +661,12 @@ static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx) dsc.bg_img_opa = disp_refr->bg_opa; dsc.bg_color = disp_refr->bg_color; dsc.bg_opa = disp_refr->bg_opa; - draw_ctx->draw_bg(draw_ctx, &dsc, draw_ctx->buf_area); + draw_ctx->draw_bg(draw_ctx, &dsc, &a); } else if(disp_refr->bg_img) { lv_img_header_t header; - lv_res_t res; - res = lv_img_decoder_get_info(disp_refr->bg_img, &header); + lv_res_t res = lv_img_decoder_get_info(disp_refr->bg_img, &header); if(res == LV_RES_OK) { - lv_area_t a; - lv_area_set(&a, 0, 0, header.w - 1, header.h - 1); lv_draw_img_dsc_t dsc; lv_draw_img_dsc_init(&dsc); dsc.opa = disp_refr->bg_opa; @@ -642,18 +684,31 @@ static void lv_refr_area_part(lv_draw_ctx_t * draw_ctx) lv_draw_rect(draw_ctx, &dsc, draw_ctx->buf_area); } } - /*Refresh the previous screen if any*/ - if(disp_refr->prev_scr) { - if(top_prev_scr == NULL) top_prev_scr = disp_refr->prev_scr; - lv_refr_obj_and_children(draw_ctx, top_prev_scr); + + if(disp_refr->draw_prev_over_act) { + if(top_act_scr == NULL) top_act_scr = disp_refr->act_scr; + refr_obj_and_children(draw_ctx, top_act_scr); + + /*Refresh the previous screen if any*/ + if(disp_refr->prev_scr) { + if(top_prev_scr == NULL) top_prev_scr = disp_refr->prev_scr; + refr_obj_and_children(draw_ctx, top_prev_scr); + } + } + else { + /*Refresh the previous screen if any*/ + if(disp_refr->prev_scr) { + if(top_prev_scr == NULL) top_prev_scr = disp_refr->prev_scr; + refr_obj_and_children(draw_ctx, top_prev_scr); + } + + if(top_act_scr == NULL) top_act_scr = disp_refr->act_scr; + refr_obj_and_children(draw_ctx, top_act_scr); } - if(top_act_scr == NULL) top_act_scr = disp_refr->act_scr; - lv_refr_obj_and_children(draw_ctx, top_act_scr); - /*Also refresh top and sys layer unconditionally*/ - lv_refr_obj_and_children(draw_ctx, lv_disp_get_layer_top(disp_refr)); - lv_refr_obj_and_children(draw_ctx, lv_disp_get_layer_sys(disp_refr)); + refr_obj_and_children(draw_ctx, lv_disp_get_layer_top(disp_refr)); + refr_obj_and_children(draw_ctx, lv_disp_get_layer_sys(disp_refr)); /*In true double buffered mode flush only once when all areas were rendered. *In normal mode flush after every area*/ @@ -672,32 +727,32 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) { lv_obj_t * found_p = NULL; + if(_lv_area_is_in(area_p, &obj->coords, 0) == false) return NULL; + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL; + if(_lv_obj_get_layer_type(obj) != LV_LAYER_TYPE_NONE) return NULL; + /*If this object is fully cover the draw area then check the children too*/ - if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) { - lv_cover_check_info_t info; - info.res = LV_COVER_RES_COVER; - info.area = area_p; - lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); - if(info.res == LV_COVER_RES_MASKED) return NULL; + lv_cover_check_info_t info; + info.res = LV_COVER_RES_COVER; + info.area = area_p; + lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); + if(info.res == LV_COVER_RES_MASKED) return NULL; - uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); - for(i = 0; i < child_cnt; i++) { - lv_obj_t * child = obj->spec_attr->children[i]; - found_p = lv_refr_get_top_obj(area_p, child); + uint32_t i; + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + found_p = lv_refr_get_top_obj(area_p, child); - /*If a children is ok then break*/ - if(found_p != NULL) { - break; - } + /*If a children is ok then break*/ + if(found_p != NULL) { + break; } + } - /*If no better children use this object*/ - if(found_p == NULL) { - if(info.res == LV_COVER_RES_COVER) { - found_p = obj; - } - } + /*If no better children use this object*/ + if(found_p == NULL && info.res == LV_COVER_RES_COVER) { + found_p = obj; } return found_p; @@ -708,7 +763,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) * @param top_p pointer to an objects. Start the drawing from it. * @param mask_p pointer to an area, the objects will be drawn only here */ -static void lv_refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) +static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) { /*Normally always will be a top_obj (at least the screen) *but in special cases (e.g. if the screen has alpha) it won't. @@ -717,7 +772,7 @@ static void lv_refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_ob if(top_obj == NULL) return; /*Shouldn't happen*/ /*Refresh the top object and its children*/ - lv_refr_obj(draw_ctx, top_obj); + refr_obj(draw_ctx, top_obj); /*Draw the 'younger' sibling objects because they can be on top_obj*/ lv_obj_t * parent; @@ -737,7 +792,7 @@ static void lv_refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_ob } else { /*Refresh the objects*/ - lv_refr_obj(draw_ctx, child); + refr_obj(draw_ctx, child); } } @@ -754,6 +809,160 @@ static void lv_refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_ob } } + +static lv_res_t layer_get_area(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj, lv_layer_type_t layer_type, + lv_area_t * layer_area_out) +{ + lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); + lv_area_t obj_coords_ext; + lv_obj_get_coords(obj, &obj_coords_ext); + lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size); + + if(layer_type == LV_LAYER_TYPE_TRANSFORM) { + /*Get the transformed area and clip it to the current clip area. + *This area needs to be updated on the screen.*/ + lv_area_t clip_coords_for_obj; + lv_area_t tranf_coords = obj_coords_ext; + lv_obj_get_transformed_area(obj, &tranf_coords, false, false); + if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &tranf_coords)) { + return LV_RES_INV; + } + + /*Transform back (inverse) the transformed area. + *It will tell which area of the non-transformed widget needs to be redrawn + *in order to cover transformed area after transformation.*/ + lv_area_t inverse_clip_coords_for_obj = clip_coords_for_obj; + lv_obj_get_transformed_area(obj, &inverse_clip_coords_for_obj, false, true); + if(!_lv_area_intersect(&inverse_clip_coords_for_obj, &inverse_clip_coords_for_obj, &obj_coords_ext)) { + return LV_RES_INV; + } + + *layer_area_out = inverse_clip_coords_for_obj; + } + else if(layer_type == LV_LAYER_TYPE_SIMPLE) { + lv_area_t clip_coords_for_obj; + if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &obj_coords_ext)) { + return LV_RES_INV; + } + *layer_area_out = clip_coords_for_obj; + } + else { + LV_LOG_WARN("Unhandled intermediate layer type"); + return LV_RES_INV; + } + + return LV_RES_OK; +} + +static void layer_alpha_test(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags) +{ + bool has_alpha; + /*If globally the layer has alpha maybe this smaller section has not (e.g. not on a rounded corner) + *If turns out that this section has no alpha renderer can choose faster algorithms*/ + if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) { + /*Test for alpha by assuming there is no alpha. If it fails, fall back to rendering with alpha*/ + has_alpha = true; + if(_lv_area_is_in(&layer_ctx->area_act, &obj->coords, 0)) { + lv_cover_check_info_t info; + info.res = LV_COVER_RES_COVER; + info.area = &layer_ctx->area_act; + lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); + if(info.res == LV_COVER_RES_COVER) has_alpha = false; + } + + if(has_alpha) { + layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_alpha - 1; + } + } + else { + has_alpha = false; + } + + if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2; + lv_draw_layer_adjust(draw_ctx, layer_ctx, has_alpha ? LV_DRAW_LAYER_FLAG_HAS_ALPHA : LV_DRAW_LAYER_FLAG_NONE); +} + + +void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +{ + /*Do not refresh hidden objects*/ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; + lv_layer_type_t layer_type = _lv_obj_get_layer_type(obj); + if(layer_type == LV_LAYER_TYPE_NONE) { + lv_obj_redraw(draw_ctx, obj); + } + else { + lv_opa_t opa = lv_obj_get_style_opa(obj, 0); + if(opa < LV_OPA_MIN) return; + + lv_area_t layer_area_full; + lv_res_t res = layer_get_area(draw_ctx, obj, layer_type, &layer_area_full); + if(res != LV_RES_OK) return; + + lv_draw_layer_flags_t flags = LV_DRAW_LAYER_FLAG_HAS_ALPHA; + + if(_lv_area_is_in(&layer_area_full, &obj->coords, 0)) { + lv_cover_check_info_t info; + info.res = LV_COVER_RES_COVER; + info.area = &layer_area_full; + lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); + if(info.res == LV_COVER_RES_COVER) flags &= ~LV_DRAW_LAYER_FLAG_HAS_ALPHA; + } + + if(layer_type == LV_LAYER_TYPE_SIMPLE) flags |= LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE; + + lv_draw_layer_ctx_t * layer_ctx = lv_draw_layer_create(draw_ctx, &layer_area_full, flags); + if(layer_ctx == NULL) { + LV_LOG_WARN("Couldn't create a new layer context"); + return; + } + lv_point_t pivot = { + .x = lv_obj_get_style_transform_pivot_x(obj, 0), + .y = lv_obj_get_style_transform_pivot_y(obj, 0) + }; + + lv_draw_img_dsc_t draw_dsc; + lv_draw_img_dsc_init(&draw_dsc); + draw_dsc.opa = opa; + draw_dsc.angle = lv_obj_get_style_transform_angle(obj, 0); + if(draw_dsc.angle > 3600) draw_dsc.angle -= 3600; + else if(draw_dsc.angle < 0) draw_dsc.angle += 3600; + + draw_dsc.zoom = lv_obj_get_style_transform_zoom(obj, 0); + draw_dsc.blend_mode = lv_obj_get_style_blend_mode(obj, 0); + draw_dsc.antialias = disp_refr->driver->antialiasing; + + if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { + layer_ctx->area_act = layer_ctx->area_full; + layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_no_alpha - 1; + if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2; + } + + while(layer_ctx->area_act.y1 <= layer_area_full.y2) { + if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { + layer_alpha_test(obj, draw_ctx, layer_ctx, flags); + } + + lv_obj_redraw(draw_ctx, obj); + + draw_dsc.pivot.x = obj->coords.x1 + pivot.x - draw_ctx->buf_area->x1; + draw_dsc.pivot.y = obj->coords.y1 + pivot.y - draw_ctx->buf_area->y1; + + /*With LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE it should also go the next chunk*/ + lv_draw_layer_blend(draw_ctx, layer_ctx, &draw_dsc); + + if((flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) == 0) break; + + layer_ctx->area_act.y1 = layer_ctx->area_act.y2 + 1; + layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_no_alpha - 1; + } + + lv_draw_layer_destroy(draw_ctx, layer_ctx); + } +} + + static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area_h) { int32_t max_row = (uint32_t)disp->driver->draw_buf->size / area_w; @@ -986,6 +1195,18 @@ static void draw_buf_flush(lv_disp_t * disp) while(draw_buf->flushing) { if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); } + + /*If the screen is transparent initialize it when the flushing is ready*/ +#if LV_COLOR_SCREEN_TRANSP + if(disp_refr->driver->screen_transp) { + if(disp_refr->driver->clear_cb) { + disp_refr->driver->clear_cb(disp_refr->driver, disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size); + } + else { + lv_memset_00(disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size * LV_IMG_PX_SIZE_ALPHA_BYTE); + } + } +#endif } draw_buf->flushing = 1; diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h index 984168a96..72e8d6c39 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h @@ -61,7 +61,7 @@ void lv_refr_now(lv_disp_t * disp); * @param draw pointer to an initialized draw context * @param obj the start object from the redraw should start */ -void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); +void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); /** * Invalidate an area on display to redraw it diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk new file mode 100644 index 000000000..17219b07e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk @@ -0,0 +1,6 @@ +CSRCS += lv_gpu_arm2d.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c new file mode 100644 index 000000000..7777fe21b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c @@ -0,0 +1,1376 @@ +/** + * @file lv_gpu_arm2d.c + * + */ + +/********************* + * INCLUDES + *********************/ +#if defined(__clang__) + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wreserved-identifier" + #pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" + #pragma clang diagnostic ignored "-Wmissing-variable-declarations" + #pragma clang diagnostic ignored "-Wcast-qual" + #pragma clang diagnostic ignored "-Wcast-align" + #pragma clang diagnostic ignored "-Wextra-semi-stmt" + #pragma clang diagnostic ignored "-Wsign-conversion" + #pragma clang diagnostic ignored "-Wunused-function" + #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" + #pragma clang diagnostic ignored "-Wdouble-promotion" + #pragma clang diagnostic ignored "-Wunused-parameter" + #pragma clang diagnostic ignored "-Wimplicit-float-conversion" + #pragma clang diagnostic ignored "-Wimplicit-int-conversion" + #pragma clang diagnostic ignored "-Wtautological-pointer-compare" + #pragma clang diagnostic ignored "-Wsign-compare" + #pragma clang diagnostic ignored "-Wfloat-conversion" + #pragma clang diagnostic ignored "-Wmissing-prototypes" + #pragma clang diagnostic ignored "-Wpadded" + #pragma clang diagnostic ignored "-Wundef" + #pragma clang diagnostic ignored "-Wdeclaration-after-statement" + #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" + #pragma clang diagnostic ignored "-Wunused-variable" + #pragma clang diagnostic ignored "-Wunused-but-set-variable" + #pragma clang diagnostic ignored "-Wint-conversion" +#endif + + +#include "lv_gpu_arm2d.h" +#include "../../core/lv_refr.h" + +#if LV_USE_GPU_ARM2D +#include "arm_2d.h" +#include "__arm_2d_impl.h" + + +#if defined(__IS_COMPILER_ARM_COMPILER_5__) + #pragma diag_suppress 174,177,188,68,513,144,1296 +#elif defined(__IS_COMPILER_IAR__) + #pragma diag_suppress=Pa093 +#elif defined(__IS_COMPILER_GCC__) + #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +#endif + +/********************* + * DEFINES + *********************/ +#if ( !defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ + || !__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ +&& LV_COLOR_DEPTH == 32 \ +&& !defined(__ARM_2D_LVGL_CFG_NO_WARNING__) +#warning Please set macro __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ to 1 to get more acceleration opportunities. Or you can define macro __ARM_2D_LVGL_CFG_NO_WARNING__ to suppress this warning. +#endif + +#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) + +#if LV_COLOR_DEPTH == 16 +#define arm_2d_fill_colour arm_2d_rgb16_fill_colour +#define arm_2d_fill_colour_with_alpha arm_2d_rgb565_fill_colour_with_alpha +#define arm_2d_fill_colour_with_mask arm_2d_rgb565_fill_colour_with_mask +#define arm_2d_fill_colour_with_mask_and_opacity \ + arm_2d_rgb565_fill_colour_with_mask_and_opacity +#define arm_2d_tile_copy arm_2d_rgb16_tile_copy +#define arm_2d_alpha_blending arm_2d_rgb565_alpha_blending +#define arm_2d_tile_copy_with_src_mask arm_2d_rgb565_tile_copy_with_src_mask +#define arm_2d_color_t arm_2d_color_rgb565_t + +/* arm-2d direct mode apis */ +#define __arm_2d_impl_colour_filling __arm_2d_impl_rgb16_colour_filling +#define __arm_2d_impl_colour_filling_with_opacity \ + __arm_2d_impl_rgb565_colour_filling_with_opacity +#define __arm_2d_impl_colour_filling_mask \ + __arm_2d_impl_rgb565_colour_filling_mask +#define __arm_2d_impl_colour_filling_mask_opacity \ + __arm_2d_impl_rgb565_colour_filling_mask_opacity +#define __arm_2d_impl_copy __arm_2d_impl_rgb16_copy +#define __arm_2d_impl_alpha_blending __arm_2d_impl_rgb565_alpha_blending +#define __arm_2d_impl_src_msk_copy __arm_2d_impl_rgb565_src_msk_copy +#define __arm_2d_impl_src_chn_msk_copy __arm_2d_impl_rgb565_src_chn_msk_copy +#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb16_cl_key_copy +#define __arm_2d_impl_alpha_blending_colour_keying \ + __arm_2d_impl_rgb565_alpha_blending_colour_keying +#define arm_2d_tile_transform_with_src_mask_and_opacity \ + arm_2d_rgb565_tile_transform_with_src_mask_and_opacity +#define arm_2d_tile_transform_with_opacity \ + arm_2d_rgb565_tile_transform_with_opacity + +#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_RGB565 + +#define color_int uint16_t + +#elif LV_COLOR_DEPTH == 32 +#define arm_2d_fill_colour arm_2d_rgb32_fill_colour +#define arm_2d_fill_colour_with_alpha arm_2d_cccn888_fill_colour_with_alpha +#define arm_2d_fill_colour_with_mask arm_2d_cccn888_fill_colour_with_mask +#define arm_2d_fill_colour_with_mask_and_opacity \ + arm_2d_cccn888_fill_colour_with_mask_and_opacity +#define arm_2d_tile_copy arm_2d_rgb32_tile_copy +#define arm_2d_alpha_blending arm_2d_cccn888_alpha_blending +#define arm_2d_tile_copy_with_src_mask arm_2d_cccn888_tile_copy_with_src_mask +#define arm_2d_color_t arm_2d_color_cccn888_t + +/* arm-2d direct mode apis */ +#define __arm_2d_impl_colour_filling __arm_2d_impl_rgb32_colour_filling +#define __arm_2d_impl_colour_filling_with_opacity \ + __arm_2d_impl_cccn888_colour_filling_with_opacity +#define __arm_2d_impl_colour_filling_mask \ + __arm_2d_impl_cccn888_colour_filling_mask +#define __arm_2d_impl_colour_filling_mask_opacity \ + __arm_2d_impl_cccn888_colour_filling_mask_opacity +#define __arm_2d_impl_copy __arm_2d_impl_rgb32_copy +#define __arm_2d_impl_alpha_blending __arm_2d_impl_cccn888_alpha_blending +#define __arm_2d_impl_src_msk_copy __arm_2d_impl_cccn888_src_msk_copy +#define __arm_2d_impl_src_chn_msk_copy __arm_2d_impl_cccn888_src_chn_msk_copy +#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb32_cl_key_copy +#define __arm_2d_impl_alpha_blending_colour_keying \ + __arm_2d_impl_cccn888_alpha_blending_colour_keying +#define arm_2d_tile_transform_with_src_mask_and_opacity \ + arm_2d_cccn888_tile_transform_with_src_mask_and_opacity +#define arm_2d_tile_transform_with_opacity \ + arm_2d_cccn888_tile_transform_with_opacity + +#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_CCCN888 + +#define color_int uint32_t + +#else +#error The specified LV_COLOR_DEPTH is not supported by this version of lv_gpu_arm2d.c. +#endif + +/* *INDENT-OFF* */ +#define __PREPARE_LL_ACCELERATION__() \ + int32_t src_stride = lv_area_get_width(coords); \ + \ + uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA \ + ? LV_IMG_PX_SIZE_ALPHA_BYTE \ + : sizeof(lv_color_t); \ + \ + const uint8_t * src_buf_tmp = src_buf; \ + src_buf_tmp += src_stride \ + * (draw_area.y1 - coords->y1) \ + * px_size_byte; \ + src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; \ + \ + lv_area_t blend_area2; \ + if(!_lv_area_intersect(&blend_area2, \ + &draw_area, \ + draw_ctx->clip_area)) return; \ + \ + int32_t w = lv_area_get_width(&blend_area2); \ + int32_t h = lv_area_get_height(&blend_area2); \ + \ + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); \ + \ + lv_color_t * dest_buf = draw_ctx->buf; \ + dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1) \ + + (blend_area2.x1 - draw_ctx->buf_area->x1); \ + \ + arm_2d_size_t copy_size = { \ + .iWidth = lv_area_get_width(&blend_area2), \ + .iHeight = lv_area_get_height(&blend_area2), \ + } + +#define __PREPARE_TARGET_TILE__(__blend_area) \ + static arm_2d_tile_t target_tile; \ + static arm_2d_region_t target_region; \ + \ + lv_color_t * dest_buf = draw_ctx->buf; \ + \ + target_tile = (arm_2d_tile_t) { \ + .tRegion = { \ + .tSize = { \ + .iWidth = lv_area_get_width(draw_ctx->buf_area), \ + .iHeight = lv_area_get_height(draw_ctx->buf_area), \ + }, \ + }, \ + .tInfo.bIsRoot = true, \ + .phwBuffer = (uint16_t *)draw_ctx->buf, \ + }; \ + \ + target_region = (arm_2d_region_t) { \ + .tLocation = { \ + .iX = (__blend_area).x1 - draw_ctx->buf_area->x1, \ + .iY = (__blend_area).y1 - draw_ctx->buf_area->y1, \ + }, \ + .tSize = { \ + .iWidth = lv_area_get_width(&(__blend_area)), \ + .iHeight = lv_area_get_height(&(__blend_area)), \ + }, \ + } + +#define __PREPARE_SOURCE_TILE__(__dsc, __blend_area) \ + static arm_2d_tile_t source_tile_orig; \ + static arm_2d_tile_t source_tile; \ + const lv_color_t * src_buf = (__dsc)->src_buf; \ + if (src_buf) { \ + source_tile_orig = (arm_2d_tile_t) { \ + .tRegion = { \ + .tSize = { \ + .iWidth = lv_area_get_width((__dsc)->blend_area), \ + .iHeight = lv_area_get_height((__dsc)->blend_area), \ + }, \ + }, \ + .tInfo.bIsRoot = true, \ + .phwBuffer = (uint16_t *)src_buf, \ + }; \ + \ + arm_2d_tile_generate_child( \ + &source_tile_orig, \ + (arm_2d_region_t []) { \ + { \ + .tLocation = { \ + .iX = (__blend_area).x1 - (__dsc)->blend_area->x1, \ + .iY = (__blend_area).y1 - (__dsc)->blend_area->y1, \ + }, \ + .tSize = source_tile_orig.tRegion.tSize, \ + } \ + }, \ + &source_tile, \ + false); \ + source_tile.tInfo.bDerivedResource = true; \ + } + +#define __PREPARE_MASK_TILE__(__dsc, __blend_area, __mask, __is_chn) \ + static arm_2d_tile_t mask_tile_orig; \ + static arm_2d_tile_t mask_tile; \ + if(NULL != (__mask)) { \ + mask_tile_orig = (arm_2d_tile_t) { \ + .tRegion = { \ + .tSize = { \ + .iWidth = lv_area_get_width((__dsc)->mask_area), \ + .iHeight = lv_area_get_height((__dsc)->mask_area), \ + }, \ + }, \ + .tInfo = { \ + .bIsRoot = true, \ + .bHasEnforcedColour = true, \ + .tColourInfo = { \ + .chScheme = (__is_chn) ? ARM_2D_CHANNEL_8in32 \ + : ARM_2D_COLOUR_8BIT, \ + }, \ + }, \ + .pchBuffer = ((uint8_t *)(__mask)) + (__is_chn) ? 3 : 0, \ + }; \ + \ + arm_2d_tile_generate_child( \ + &mask_tile_orig, \ + (arm_2d_region_t []) { \ + { \ + .tLocation = { \ + .iX = (__dsc)->mask_area->x1 - (__blend_area).x1, \ + .iY = (__dsc)->mask_area->y1 - (__blend_area).y1, \ + }, \ + .tSize = mask_tile_orig.tRegion.tSize, \ + } \ + }, \ + &mask_tile, \ + false); \ + mask_tile.tInfo.bDerivedResource = true; \ + } +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +#define __RECOLOUR_WRAPPER(...) \ + do { \ + lv_color_t *rgb_tmp_buf = NULL; \ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { \ + rgb_tmp_buf \ + = lv_mem_buf_get(src_w * src_h * sizeof(lv_color_t)); \ + if (NULL == rgb_tmp_buf) { \ + LV_LOG_WARN( \ + "Failed to allocate memory for accelerating recolour, " \ + "use normal route instead."); \ + break; \ + } \ + lv_memcpy(rgb_tmp_buf, src_buf, src_w * src_h * sizeof(lv_color_t));\ + arm_2d_size_t copy_size = { \ + .iWidth = src_w, \ + .iHeight = src_h, \ + }; \ + /* apply re-colour */ \ + __arm_2d_impl_colour_filling_with_opacity( \ + (color_int *)rgb_tmp_buf, \ + src_w, \ + ©_size, \ + (color_int)draw_dsc->recolor.full, \ + draw_dsc->recolor_opa); \ + \ + /* replace src_buf for the following operation */ \ + src_buf = (const uint8_t *)rgb_tmp_buf; \ + } \ + __VA_ARGS__ \ + if (NULL != rgb_tmp_buf) { \ + lv_mem_buf_release(rgb_tmp_buf); \ + } \ + } while(0); +/* *INDENT-ON* */ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +#if __ARM_2D_HAS_HW_ACC__ +LV_ATTRIBUTE_FAST_MEM +static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, + const arm_2d_region_t * region, + lv_color_t color, + lv_opa_t opa, + const arm_2d_tile_t * mask_tile); + +LV_ATTRIBUTE_FAST_MEM +static bool lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile, + const arm_2d_region_t * region, + arm_2d_tile_t * source_tile, + lv_opa_t opa, + arm_2d_tile_t * mask_tile); +#else + +static void convert_cb(const lv_area_t * dest_area, + const void * src_buf, + lv_coord_t src_w, + lv_coord_t src_h, + lv_coord_t src_stride, + const lv_draw_img_dsc_t * draw_dsc, + lv_img_cf_t cf, + lv_color_t * cbuf, + lv_opa_t * abuf); + +LV_ATTRIBUTE_FAST_MEM +static bool arm_2d_fill_normal(lv_color_t * dest_buf, + const lv_area_t * dest_area, + lv_coord_t dest_stride, + lv_color_t color, + lv_opa_t opa, + const lv_opa_t * mask, + lv_coord_t mask_stride); + +LV_ATTRIBUTE_FAST_MEM +static bool arm_2d_copy_normal(lv_color_t * dest_buf, + const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, + lv_coord_t src_stride, + lv_opa_t opa, + const lv_opa_t * mask, + lv_coord_t mask_stride); +#endif + +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM +static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx); +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, + const lv_draw_img_dsc_t * draw_dsc, + const lv_area_t * coords, + const uint8_t * src_buf, + lv_img_cf_t cf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_arm2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + arm_2d_init(); + + lv_draw_sw_init_ctx(drv, draw_ctx); + + lv_draw_arm2d_ctx_t * arm2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; + + arm2d_draw_ctx->blend = lv_draw_arm2d_blend; + arm2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_arm2d_wait_cb; + +#if !__ARM_2D_HAS_HW_ACC__ + arm2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_arm2d_img_decoded; +#endif + +} + +void lv_draw_arm2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + LV_UNUSED(drv); + LV_UNUSED(draw_ctx); +} + +extern void test_flush(lv_color_t * color_p); + +#if __ARM_2D_HAS_HW_ACC__ +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) +{ + const lv_opa_t * mask; + if(dsc->mask_buf == NULL) mask = NULL; + if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; + else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; + else mask = dsc->mask_buf; + + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) { + return; + } + + bool is_accelerated = false; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL + && lv_area_get_size(&blend_area) > 100) { + + __PREPARE_TARGET_TILE__(blend_area); + __PREPARE_SOURCE_TILE__(dsc, blend_area); + __PREPARE_MASK_TILE__(dsc, blend_area, mask, false); + + if(src_buf) { + is_accelerated = lv_draw_arm2d_tile_copy( + &target_tile, + &target_region, + &source_tile, + dsc->opa, + (NULL == mask) ? NULL : &mask_tile); + } + else { + is_accelerated = lv_draw_arm2d_fill_colour( + &target_tile, + &target_region, + dsc->color, + dsc->opa, + (NULL == mask) ? NULL : &mask_tile); + } + } + + if(!is_accelerated) { + lv_draw_sw_blend_basic(draw_ctx, dsc); + } +} + + +LV_ATTRIBUTE_FAST_MEM +static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, + const arm_2d_region_t * region, + lv_color_t color, + lv_opa_t opa, + const arm_2d_tile_t * mask_tile) +{ + arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE; + + if(NULL == mask_tile) { + if(opa >= LV_OPA_MAX) { + result = arm_2d_fill_colour(target_tile, region, color.full); + } + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + result = arm_2d_fill_colour_with_alpha( + target_tile, + region, + (arm_2d_color_t) { + color.full + }, + opa); +#endif + } + } + else { + + if(opa >= LV_OPA_MAX) { + result = arm_2d_fill_colour_with_mask( + target_tile, + region, + mask_tile, + (arm_2d_color_t) { + color.full + }); + } + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + result = arm_2d_fill_colour_with_mask_and_opacity( + target_tile, + region, + mask_tile, + (arm_2d_color_t) { + color.full + }, + opa); +#endif + } + } + + if(result < 0) { + /* error detected */ + return false; + } + + return true; + +} + +LV_ATTRIBUTE_FAST_MEM +static bool lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile, + const arm_2d_region_t * region, + arm_2d_tile_t * source_tile, + lv_opa_t opa, + arm_2d_tile_t * mask_tile) +{ + arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE; + + if(NULL == mask_tile) { + if(opa >= LV_OPA_MAX) { + result = arm_2d_tile_copy(source_tile, + target_tile, + region, + ARM_2D_CP_MODE_COPY); + } +#if LV_COLOR_SCREEN_TRANSP + else { + return false; /* not supported */ + } +#else + else { + result = arm_2d_alpha_blending(source_tile, + target_tile, + region, + opa); + } +#endif + } + else { +#if LV_COLOR_SCREEN_TRANSP + return false; /* not support */ +#else + + if(opa >= LV_OPA_MAX) { + result = arm_2d_tile_copy_with_src_mask(source_tile, + mask_tile, + target_tile, + region, + ARM_2D_CP_MODE_COPY); + } + else { + return false; + } +#endif + } + + if(result < 0) { + /* error detected */ + return false; + } + + return true; +} + +static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + arm_2d_op_wait_async(NULL); + if(disp->driver && disp->driver->wait_cb) { + disp->driver->wait_cb(disp->driver); + } + lv_draw_sw_wait_for_finish(draw_ctx); +} +#else + + +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) +{ + const lv_opa_t * mask; + if(dsc->mask_buf == NULL) mask = NULL; + if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; + else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; + else mask = dsc->mask_buf; + + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; + + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + bool is_accelerated = false; + do { + if(NULL != disp->driver->set_px_cb) { + break; + } + + lv_color_t * dest_buf = draw_ctx->buf; + dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + + (blend_area.x1 - draw_ctx->buf_area->x1); + + const lv_color_t * src_buf = dsc->src_buf; + lv_coord_t src_stride; + if(src_buf) { + src_stride = lv_area_get_width(dsc->blend_area); + src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1); + } + else { + src_stride = 0; + } + + lv_coord_t mask_stride; + if(mask) { + mask_stride = lv_area_get_width(dsc->mask_area); + mask += mask_stride * (blend_area.y1 - dsc->mask_area->y1) + (blend_area.x1 - dsc->mask_area->x1); + } + else { + mask_stride = 0; + } + + lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + + if(dsc->src_buf == NULL) { + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + is_accelerated = arm_2d_fill_normal(dest_buf, + &blend_area, + dest_stride, + dsc->color, + dsc->opa, + mask, + mask_stride); + } +#if LV_DRAW_COMPLEX + else { + break; + } +#endif + } + else { + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + is_accelerated = arm_2d_copy_normal(dest_buf, + &blend_area, + dest_stride, + src_buf, + src_stride, + dsc->opa, + mask, + mask_stride); + } +#if LV_DRAW_COMPLEX + else { + break; + } +#endif + } + } while(0); + + if(!is_accelerated) lv_draw_sw_blend_basic(draw_ctx, dsc); +} + +LV_ATTRIBUTE_FAST_MEM +static bool arm_2d_fill_normal(lv_color_t * dest_buf, + const lv_area_t * dest_area, + lv_coord_t dest_stride, + lv_color_t color, + lv_opa_t opa, + const lv_opa_t * mask, + lv_coord_t mask_stride) +{ + arm_2d_size_t target_size = { + .iWidth = lv_area_get_width(dest_area), + .iHeight = lv_area_get_height(dest_area), + }; + + /*No mask*/ + if(mask == NULL) { + if(opa >= LV_OPA_MAX) { + __arm_2d_impl_colour_filling((color_int *)dest_buf, + dest_stride, + &target_size, + color.full); + } + /*Has opacity*/ + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + __arm_2d_impl_colour_filling_with_opacity((color_int *)dest_buf, + dest_stride, + &target_size, + color.full, + opa); +#endif + } + } + /*Masked*/ + else { + /*Only the mask matters*/ + if(opa >= LV_OPA_MAX) { + __arm_2d_impl_colour_filling_mask((color_int *)dest_buf, + dest_stride, + (uint8_t *)mask, + mask_stride, + &target_size, + color.full); + } + /*With opacity*/ + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + __arm_2d_impl_colour_filling_mask_opacity((color_int *)dest_buf, + dest_stride, + (uint8_t *)mask, + mask_stride, + &target_size, + color.full, + opa); +#endif + } + } + + return true; +} + + +LV_ATTRIBUTE_FAST_MEM +static bool arm_2d_copy_normal(lv_color_t * dest_buf, + const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, + lv_coord_t src_stride, + lv_opa_t opa, + const lv_opa_t * mask, + lv_coord_t mask_stride) + +{ + int32_t w = lv_area_get_width(dest_area); + int32_t h = lv_area_get_height(dest_area); + + arm_2d_size_t copy_size = { + .iWidth = lv_area_get_width(dest_area), + .iHeight = lv_area_get_height(dest_area), + }; + +#if LV_COLOR_SCREEN_TRANSP + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); +#endif + + /*Simple fill (maybe with opacity), no masking*/ + if(mask == NULL) { + if(opa >= LV_OPA_MAX) { + __arm_2d_impl_copy((color_int *)src_buf, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size); + } + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + __arm_2d_impl_alpha_blending((color_int *)src_buf, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size, + opa); +#endif + } + } + /*Masked*/ + else { + /*Only the mask matters*/ + if(opa > LV_OPA_MAX) { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + __arm_2d_impl_src_msk_copy((color_int *)src_buf, + src_stride, + (uint8_t *)mask, + mask_stride, + ©_size, + (color_int *)dest_buf, + dest_stride, + ©_size); +#endif + } + /*Handle opa and mask values too*/ + else { +#if LV_COLOR_SCREEN_TRANSP + return false; +#else + __arm_2d_impl_gray8_alpha_blending((uint8_t *)mask, + mask_stride, + (uint8_t *)mask, + mask_stride, + ©_size, + opa); + + __arm_2d_impl_src_msk_copy((color_int *)src_buf, + src_stride, + (uint8_t *)mask, + mask_stride, + ©_size, + (color_int *)dest_buf, + dest_stride, + ©_size); +#endif + } + } + + return true; +} + +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, + const lv_draw_img_dsc_t * draw_dsc, + const lv_area_t * coords, + const uint8_t * src_buf, + lv_img_cf_t cf) +{ + /*Use the clip area as draw area*/ + lv_area_t draw_area; + lv_area_copy(&draw_area, draw_ctx->clip_area); + + bool mask_any = lv_draw_mask_is_any(&draw_area); + bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; + + lv_area_t blend_area; + lv_draw_sw_blend_dsc_t blend_dsc; + + lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); + blend_dsc.opa = draw_dsc->opa; + blend_dsc.blend_mode = draw_dsc->blend_mode; + blend_dsc.blend_area = &blend_area; + + /*The simplest case just copy the pixels into the draw_buf*/ + if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { + blend_dsc.src_buf = (const lv_color_t *)src_buf; + + blend_dsc.blend_area = coords; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } + else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) { + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_area = coords; + blend_dsc.src_buf = NULL; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + + blend_dsc.blend_area = coords; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } +#if LV_COLOR_DEPTH == 16 + else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP) { + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + blend_dsc.src_buf = (const lv_color_t *)src_buf; + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_buf += sizeof(lv_color_t) * src_w * src_h; + blend_dsc.blend_area = coords; + blend_dsc.mask_area = coords; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } +#endif + /*In the other cases every pixel need to be checked one-by-one*/ + else { + blend_area.x1 = draw_ctx->clip_area->x1; + blend_area.x2 = draw_ctx->clip_area->x2; + blend_area.y1 = draw_ctx->clip_area->y1; + blend_area.y2 = draw_ctx->clip_area->y2; + + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + lv_coord_t blend_h = lv_area_get_height(&blend_area); + lv_coord_t blend_w = lv_area_get_width(&blend_area); + + uint32_t max_buf_size = MAX_BUF_SIZE; + uint32_t blend_size = lv_area_get_size(&blend_area); + uint32_t buf_h; + uint32_t buf_w = blend_w; + if(blend_size <= max_buf_size) { + buf_h = blend_h; + } + else { + /*Round to full lines*/ + buf_h = max_buf_size / blend_w; + } + + /*Create buffers and masks*/ + uint32_t buf_size = buf_w * buf_h; + + lv_color_t * rgb_buf = lv_mem_buf_get(buf_size * sizeof(lv_color_t)); + lv_opa_t * mask_buf = lv_mem_buf_get(buf_size); + blend_dsc.mask_buf = mask_buf; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + blend_dsc.src_buf = rgb_buf; + lv_coord_t y_last = blend_area.y2; + blend_area.y2 = blend_area.y1 + buf_h - 1; + + lv_draw_mask_res_t mask_res_def = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || + draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? + LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; + blend_dsc.mask_res = mask_res_def; + + bool is_accelerated = false; + + if(!transform) { + if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) { + /* copy with colour keying */ + + /* *INDENT-OFF* */ + __RECOLOUR_WRAPPER( + + lv_color_t chrome_key = LV_COLOR_CHROMA_KEY; + /* calculate new chrome-key colour */ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + __ARM_2D_PIXEL_BLENDING_OPA( + (color_int *) & (draw_dsc->recolor.full), + (color_int *) & (chrome_key.full), + draw_dsc->recolor_opa + ); + } + + __PREPARE_LL_ACCELERATION__(); + + if(blend_dsc.opa >= LV_OPA_MAX) { + __arm_2d_impl_cl_key_copy( + (color_int *)src_buf_tmp, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size, + (color_int)chrome_key.full); + } + else { + __arm_2d_impl_alpha_blending_colour_keying( + (color_int *)src_buf_tmp, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size, + blend_dsc.opa, + (color_int)chrome_key.full); + } + is_accelerated = true; + ) + /* *INDENT-ON* */ + } + else if((LV_COLOR_DEPTH == 32) + && !mask_any + && (cf == LV_IMG_CF_TRUE_COLOR_ALPHA)) { + /* accelerate copy-with-source-masks-and-opacity */ + + /* *INDENT-OFF* */ + __RECOLOUR_WRAPPER( + __PREPARE_LL_ACCELERATION__(); + + uint8_t * mask_temp_buf = NULL; + if(blend_dsc.opa < LV_OPA_MAX) { + mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth); + if(NULL == mask_temp_buf) { + LV_LOG_WARN( + "Failed to allocate memory for alpha mask," + " use normal route instead."); + break; + } + lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth); + + __arm_2d_impl_gray8_colour_filling_channel_mask_opacity( + mask_temp_buf, + src_stride, + (uint32_t *) + ((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1), + src_stride, + ©_size, + 0xFF, + blend_dsc.opa); + + __arm_2d_impl_src_msk_copy( + (color_int *)src_buf_tmp, + src_stride, + mask_temp_buf, + src_stride, + ©_size, + (color_int *)dest_buf, + dest_stride, + ©_size); + + lv_mem_buf_release(mask_temp_buf); + } + else { + __arm_2d_impl_src_chn_msk_copy( + (color_int *)src_buf_tmp, + src_stride, + (uint32_t *) + ((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1), + src_stride, + ©_size, + (color_int *)dest_buf, + dest_stride, + ©_size); + } + + is_accelerated = true; + ) + /* *INDENT-ON* */ + } + else if(!mask_any && (cf == LV_IMG_CF_TRUE_COLOR)) { + /* accelerate copy-with-source-masks-and-opacity */ + + /* *INDENT-OFF* */ + __RECOLOUR_WRAPPER( + __PREPARE_LL_ACCELERATION__(); + + if(blend_dsc.opa >= LV_OPA_MAX) { + __arm_2d_impl_copy( + (color_int *)src_buf_tmp, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size); + } + else { + __arm_2d_impl_alpha_blending( + (color_int *)src_buf_tmp, + src_stride, + (color_int *)dest_buf, + dest_stride, + ©_size, + blend_dsc.opa); + } + is_accelerated = true; + ) + /* *INDENT-ON* */ + } + } + else if(!mask_any +#if defined(__ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__) && __ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__ + && (draw_dsc->antialias == 1) +#else + && (draw_dsc->antialias == 0) +#endif + && (draw_dsc->recolor_opa == LV_OPA_TRANSP) + && (((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) + || (LV_IMG_CF_TRUE_COLOR == cf)) +#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ + || ((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) + && (LV_COLOR_DEPTH == 32)) +#endif + ) + ) { + + /* *INDENT-OFF* */ + __RECOLOUR_WRAPPER( + /* accelerate transform without re-color */ + + static arm_2d_tile_t target_tile_origin; + static arm_2d_tile_t target_tile; + arm_2d_region_t clip_region; + static arm_2d_region_t target_region; + + lv_color_t * dest_buf = draw_ctx->buf; + + target_tile_origin = (arm_2d_tile_t) { + .tRegion = { + .tSize = { + .iWidth = lv_area_get_width(draw_ctx->buf_area), + .iHeight = lv_area_get_height(draw_ctx->buf_area), + }, + }, + .tInfo.bIsRoot = true, + .phwBuffer = (uint16_t *)draw_ctx->buf, + }; + + clip_region = (arm_2d_region_t) { + .tLocation = { + .iX = draw_ctx->clip_area->x1 - draw_ctx->buf_area->x1, + .iY = draw_ctx->clip_area->y1 - draw_ctx->buf_area->y1, + }, + .tSize = { + .iWidth = lv_area_get_width(draw_ctx->clip_area), + .iHeight = lv_area_get_height(draw_ctx->clip_area), + }, + }; + + arm_2d_tile_generate_child(&target_tile_origin, + &clip_region, + &target_tile, + false); + + target_region = (arm_2d_region_t) { + .tLocation = { + .iX = coords->x1 - draw_ctx->clip_area->x1, + .iY = coords->y1 - draw_ctx->clip_area->y1, + }, + .tSize = { + .iWidth = lv_area_get_width(coords), + .iHeight = lv_area_get_height(coords), + }, + }; + + static arm_2d_tile_t source_tile; + + source_tile = (arm_2d_tile_t) { + .tRegion = { + .tSize = { + .iWidth = src_w, + .iHeight = src_h, + }, + }, + .tInfo.bIsRoot = true, + .pchBuffer = (uint8_t *)src_buf, + }; + + static arm_2d_tile_t mask_tile; + mask_tile = source_tile; + + mask_tile.tInfo.bHasEnforcedColour = true; + mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32; + mask_tile.pchBuffer += 3; + + static arm_2d_location_t source_center, target_center; + source_center.iX = draw_dsc->pivot.x; + source_center.iY = draw_dsc->pivot.y; + + + if((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) || + (LV_IMG_CF_TRUE_COLOR == cf)) { + arm_2d_tile_transform_with_opacity( + &source_tile, + &target_tile, + &target_region, + source_center, + ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), + draw_dsc->zoom / 256.0f, + (color_int)LV_COLOR_CHROMA_KEY.full, + blend_dsc.opa); + + is_accelerated = true; + } + #if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ + && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ + else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) && + (LV_COLOR_DEPTH == 32)) { + arm_2d_tile_transform_with_src_mask_and_opacity( + &source_tile, + &mask_tile, + &target_tile, + &target_region, + source_center, + ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), + draw_dsc->zoom / 256.0f, + blend_dsc.opa); + + is_accelerated = true; + } + #endif + ) + /* *INDENT-ON* */ + } + + /* *INDENT-OFF* */ + if(!is_accelerated) while(blend_area.y1 <= y_last) { + /*Apply transformations if any or separate the channels*/ + lv_area_t transform_area; + lv_area_copy(&transform_area, &blend_area); + lv_area_move(&transform_area, -coords->x1, -coords->y1); + if(transform) { + lv_draw_transform(draw_ctx, &transform_area, src_buf, src_w, src_h, src_w, + draw_dsc, cf, rgb_buf, mask_buf); + } + else { + convert_cb(&transform_area, src_buf, src_w, src_h, src_w, draw_dsc, cf, rgb_buf, mask_buf); + } + + /*Apply recolor*/ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + arm_2d_size_t copy_size = { + .iWidth = buf_w, + .iHeight = buf_h, + }; + + /* apply re-colour */ + __arm_2d_impl_colour_filling_with_opacity( + (color_int *)rgb_buf, + buf_w, + ©_size, + (color_int)draw_dsc->recolor.full, + draw_dsc->recolor_opa); + } +#if LV_DRAW_COMPLEX + /*Apply the masks if any*/ + if(mask_any) { + lv_coord_t y; + lv_opa_t * mask_buf_tmp = mask_buf; + for(y = blend_area.y1; y <= blend_area.y2; y++) { + lv_draw_mask_res_t mask_res_line; + mask_res_line = lv_draw_mask_apply(mask_buf_tmp, blend_area.x1, y, blend_w); + + if(mask_res_line == LV_DRAW_MASK_RES_TRANSP) { + lv_memset_00(mask_buf_tmp, blend_w); + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + } + else if(mask_res_line == LV_DRAW_MASK_RES_CHANGED) { + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + } + mask_buf_tmp += blend_w; + } + } +#endif + + /*Blend*/ + lv_draw_sw_blend(draw_ctx, &blend_dsc); + + /*Go the the next lines*/ + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1 + buf_h - 1; + if(blend_area.y2 > y_last) blend_area.y2 = y_last; + } + + lv_mem_buf_release(mask_buf); + lv_mem_buf_release(rgb_buf); + } +} + +static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + arm_2d_op_wait_async(NULL); + if(disp->driver && disp->driver->wait_cb) { + disp->driver->wait_cb(disp->driver); + } + lv_draw_sw_wait_for_finish(draw_ctx); +} + + +#endif + + +/********************** + * STATIC FUNCTIONS + **********************/ +/* Separate the image channels to RGB and Alpha to match LV_COLOR_DEPTH settings*/ +static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +{ + LV_UNUSED(draw_dsc); + LV_UNUSED(src_h); + LV_UNUSED(src_w); + + const uint8_t * src_tmp8 = (const uint8_t *)src_buf; + lv_coord_t y; + lv_coord_t x; + + if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t px_cnt = lv_area_get_size(dest_area); + lv_memset_ff(abuf, px_cnt); + + src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); + uint32_t dest_w = lv_area_get_width(dest_area); + uint32_t dest_w_byte = dest_w * sizeof(lv_color_t); + + lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); + lv_color_t * cbuf_tmp = cbuf; + for(y = dest_area->y1; y <= dest_area->y2; y++) { + lv_memcpy(cbuf_tmp, src_tmp8, dest_w_byte); + src_tmp8 += src_stride_byte; + cbuf_tmp += dest_w; + } + + /*Make "holes" for with Chroma keying*/ + if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t i; + lv_color_t chk = LV_COLOR_CHROMA_KEY; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + uint8_t * cbuf_uint = (uint8_t *)cbuf; + uint8_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 16 + uint16_t * cbuf_uint = (uint16_t *)cbuf; + uint16_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 32 + uint32_t * cbuf_uint = (uint32_t *)cbuf; + uint32_t chk_v = chk.full; +#endif + for(i = 0; i < px_cnt; i++) { + if(chk_v == cbuf_uint[i]) abuf[i] = 0x00; + } + } + } + else if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + src_tmp8 += (src_stride * dest_area->y1 * LV_IMG_PX_SIZE_ALPHA_BYTE) + dest_area->x1 * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t src_new_line_step_px = (src_stride - lv_area_get_width(dest_area)); + lv_coord_t src_new_line_step_byte = src_new_line_step_px * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + for(y = 0; y < dest_h; y++) { + for(x = 0; x < dest_w; x++) { + abuf[x] = src_tmp8[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + cbuf[x].full = *src_tmp8; +#elif LV_COLOR_DEPTH == 16 + cbuf[x].full = *src_tmp8 + ((*(src_tmp8 + 1)) << 8); +#elif LV_COLOR_DEPTH == 32 + cbuf[x] = *((lv_color_t *) src_tmp8); + cbuf[x].ch.alpha = 0xff; +#endif + src_tmp8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + + } + cbuf += dest_w; + abuf += dest_w; + src_tmp8 += src_new_line_step_byte; + } + } + else if(cf == LV_IMG_CF_RGB565A8) { + src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); + + lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); + + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + for(y = 0; y < dest_h; y++) { + lv_memcpy(cbuf, src_tmp8, dest_w * sizeof(lv_color_t)); + cbuf += dest_w; + src_tmp8 += src_stride_byte; + } + + src_tmp8 = (const uint8_t *)src_buf; + src_tmp8 += sizeof(lv_color_t) * src_w * src_h; + src_tmp8 += src_stride * dest_area->y1 + dest_area->x1; + for(y = 0; y < dest_h; y++) { + lv_memcpy(abuf, src_tmp8, dest_w); + abuf += dest_w; + src_tmp8 += src_stride; + } + } +} + +#if 0 +static void invalidate_cache(void) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver); + else { +#if __CORTEX_M >= 0x07 + if((SCB->CCR) & (uint32_t)SCB_CCR_DC_Msk) + SCB_CleanInvalidateDCache(); +#endif + } +} +#endif + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h new file mode 100644 index 000000000..50fa5a891 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h @@ -0,0 +1,51 @@ +/** + * @file lv_gpu_arm2d.h + * + */ + +#ifndef LV_GPU_ARM2D_H +#define LV_GPU_ARM2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../hal/lv_hal_disp.h" +#include "../sw/lv_draw_sw.h" + +#if LV_USE_GPU_ARM2D + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef lv_draw_sw_ctx_t lv_draw_arm2d_ctx_t; + +struct _lv_disp_drv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_arm2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_arm2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_ARM2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_ARM2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c index 116e3b231..823f70768 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c @@ -39,12 +39,12 @@ void lv_draw_init(void) { - // backend_head = NULL; - // lv_draw_sw_init(); - // - //#if LV_USE_GPU_STM32_DMA2D == 0 - // lv_gpu_stm32_dma2d_init(); - //#endif + /*Nothing to init now*/ +} + +void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx) +{ + if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx); } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h index 8e3c6cb94..80b62e9f0 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h @@ -27,6 +27,8 @@ extern "C" { #include "lv_draw_triangle.h" #include "lv_draw_arc.h" #include "lv_draw_mask.h" +#include "lv_draw_transform.h" +#include "lv_draw_layer.h" /********************* * DEFINES @@ -40,6 +42,19 @@ typedef struct { void * user_data; } lv_draw_mask_t; +typedef struct _lv_draw_layer_ctx_t { + lv_area_t area_full; + lv_area_t area_act; + lv_coord_t max_row_with_alpha; + lv_coord_t max_row_with_no_alpha; + void * buf; + struct { + const lv_area_t * clip_area; + lv_area_t * buf_area; + void * buf; + bool screen_transp; + } original; +} lv_draw_layer_ctx_t; typedef struct _lv_draw_ctx_t { /** @@ -80,6 +95,24 @@ typedef struct _lv_draw_ctx_t { void (*draw_polygon)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points, uint16_t point_cnt); + + /** + * Get an area of a transformed image (zoomed and/or rotated) + * @param draw_ctx pointer to a draw context + * @param dest_area get this area of the result image. It assumes that the original image is placed to the 0;0 position. + * @param src_buf the source image + * @param src_w width of the source image in [px] + * @param src_h height of the source image in [px] + * @param src_stride the stride in [px]. + * @param draw_dsc an `lv_draw_img_dsc_t` descriptor containing the transformation parameters + * @param cf the color format of `src_buf` + * @param cbuf place the colors of the pixels on `dest_area` here in RGB format + * @param abuf place the opacity of the pixels on `dest_area` here + */ + void (*draw_transform)(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, + lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); + /** * Replace the buffer with a rect without decoration like radius or borders */ @@ -88,7 +121,68 @@ typedef struct _lv_draw_ctx_t { /** * Wait until all background operations are finished. (E.g. GPU operations) */ - void (*wait_for_finish)(struct _lv_draw_ctx_t * draw); + void (*wait_for_finish)(struct _lv_draw_ctx_t * draw_ctx); + + /** + * Copy an area from buffer to an other + * @param draw_ctx pointer to a draw context + * @param dest_buf copy the buffer into this buffer + * @param dest_stride the width of the dest_buf in pixels + * @param dest_area the destination area + * @param src_buf copy from this buffer + * @param src_stride the width of src_buf in pixels + * @param src_area the source area. + * + * @note dest_area and src_area must have the same width and height + * but can have different x and y position. + * @note dest_area and src_area must be clipped to the real dimensions of the buffers + */ + void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride, + const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); + + /** + * Initialize a new layer context. + * The original buffer and area data are already saved from `draw_ctx` to `layer_ctx` + * @param draw_ctx pointer to the current draw context + * @param layer_area the coordinates of the layer + * @param flags OR-ed flags from @lv_draw_layer_flags_t + * @return pointer to the layer context, or NULL on error + */ + struct _lv_draw_layer_ctx_t * (*layer_init)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + + /** + * Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`. + * It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE` + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + * @param flags OR-ed flags from @lv_draw_layer_flags_t + */ + void (*layer_adjust)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + + /** + * Blend a rendered layer to `layer_ctx->area_act` + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + * @param draw_dsc pointer to an image draw descriptor + */ + void (*layer_blend)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + const lv_draw_img_dsc_t * draw_dsc); + + /** + * Destroy a layer context. The original buffer and area data of the `draw_ctx` will be restored + * and the `layer_ctx` itself will be freed automatically. + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + */ + void (*layer_destroy)(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); + + /** + * Size of a layer context in bytes. + */ + size_t layer_instance_size; #if LV_USE_USER_DATA void * user_data; @@ -102,6 +196,9 @@ typedef struct _lv_draw_ctx_t { void lv_draw_init(void); + +void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx); + /********************** * GLOBAL VARIABLES **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk index 803e06494..f48f48fe0 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk @@ -5,6 +5,8 @@ CSRCS += lv_draw_label.c CSRCS += lv_draw_line.c CSRCS += lv_draw_mask.c CSRCS += lv_draw_rect.c +CSRCS += lv_draw_transform.c +CSRCS += lv_draw_layer.c CSRCS += lv_draw_triangle.c CSRCS += lv_img_buf.c CSRCS += lv_img_cache.c @@ -15,4 +17,9 @@ VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw" +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d/lv_draw_arm2d.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/lv_draw_nxp.mk include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl/lv_draw_sdl.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c index 320913255..41dc0f039 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c @@ -236,12 +236,21 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, if(cdsc == NULL) return LV_RES_INV; - lv_img_cf_t cf; if(lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; + else if(LV_IMG_CF_ALPHA_8BIT == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_ALPHA_8BIT; + else if(LV_IMG_CF_RGB565A8 == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_RGB565A8; else if(lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; else cf = LV_IMG_CF_TRUE_COLOR; + if(cf == LV_IMG_CF_ALPHA_8BIT) { + if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) { + /* resume normal method */ + cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + cdsc->dec_dsc.img_data = NULL; + } + } + if(cdsc->dec_dsc.error_msg != NULL) { LV_LOG_WARN("Image draw error"); diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h index 504bedae4..a88a33caf 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h @@ -31,7 +31,7 @@ extern "C" { typedef struct { - uint16_t angle; + int16_t angle; uint16_t zoom; lv_point_t pivot; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c index 8569c7dd0..7f80df453 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c @@ -202,7 +202,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw cmd_state_t cmd_state = CMD_STATE_WAIT; uint32_t i; uint32_t par_start = 0; - lv_color_t recolor; + lv_color_t recolor = lv_color_black(); lv_color_t color = lv_color_black(); int32_t letter_w; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c new file mode 100644 index 000000000..da35682d1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c @@ -0,0 +1,93 @@ +/** + * @file lv_draw_layer.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw.h" +#include "lv_draw_arc.h" +#include "../core/lv_refr.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, + lv_draw_layer_flags_t flags) +{ + if(draw_ctx->layer_init == NULL) return NULL; + + lv_draw_layer_ctx_t * layer_ctx = lv_mem_alloc(draw_ctx->layer_instance_size); + LV_ASSERT_MALLOC(layer_ctx); + if(layer_ctx == NULL) { + LV_LOG_WARN("Couldn't allocate a new layer context"); + return NULL; + } + + lv_memset_00(layer_ctx, draw_ctx->layer_instance_size); + + lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); + layer_ctx->original.buf = draw_ctx->buf; + layer_ctx->original.buf_area = draw_ctx->buf_area; + layer_ctx->original.clip_area = draw_ctx->clip_area; + layer_ctx->original.screen_transp = disp_refr->driver->screen_transp; + layer_ctx->area_full = *layer_area; + + lv_draw_layer_ctx_t * init_layer_ctx = draw_ctx->layer_init(draw_ctx, layer_ctx, flags); + if(NULL == init_layer_ctx) { + lv_mem_free(layer_ctx); + } + return init_layer_ctx; +} + +void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags) +{ + if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags); +} + +void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_img_dsc_t * draw_dsc) +{ + if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc); +} + +void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) +{ + + lv_draw_wait_for_finish(draw_ctx); + draw_ctx->buf = layer_ctx->original.buf; + draw_ctx->buf_area = layer_ctx->original.buf_area; + draw_ctx->clip_area = layer_ctx->original.clip_area; + lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); + disp_refr->driver->screen_transp = layer_ctx->original.screen_transp; + + if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx); + lv_mem_free(layer_ctx); +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h new file mode 100644 index 000000000..cd64149c4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h @@ -0,0 +1,83 @@ +/** + * @file lv_draw_layer.h + * + */ + +#ifndef LV_DRAW_LAYER_H +#define LV_DRAW_LAYER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct _lv_draw_ctx_t; +struct _lv_draw_layer_ctx_t; + +typedef enum { + LV_DRAW_LAYER_FLAG_NONE, + LV_DRAW_LAYER_FLAG_HAS_ALPHA, + LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE, +} lv_draw_layer_flags_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a new layer context. It is used to start and independent rendering session + * with the current draw_ctx + * @param draw_ctx pointer to the current draw context + * @param layer_area the coordinates of the layer + * @param flags OR-ed flags from @lv_draw_layer_flags_t + * @return pointer to the layer context, or NULL on error + */ +struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, + lv_draw_layer_flags_t flags); + +/** + * Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`. + * It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE` + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + * @param flags OR-ed flags from @lv_draw_layer_flags_t + */ +void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + +/** + * Blend a rendered layer to `layer_ctx->area_act` + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + * @param draw_dsc pointer to an image draw descriptor + */ +void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_img_dsc_t * draw_dsc); + +/** + * Destroy a layer context. + * @param draw_ctx pointer to the current draw context + * @param layer_ctx pointer to a layer context + */ +void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_LAYER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c index 430fd56ae..2170da941 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c @@ -202,7 +202,7 @@ void * lv_draw_mask_remove_custom(void * custom_id) /** * Free the data from the parameter. - * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` + * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` * @param p pointer to a mask parameter @@ -446,9 +446,6 @@ void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vert if(start_angle >= 0 && start_angle < 180) { start_side = LV_DRAW_MASK_LINE_SIDE_LEFT; } - else if(start_angle >= 180 && start_angle < 360) { - start_side = LV_DRAW_MASK_LINE_SIDE_RIGHT; - } else start_side = LV_DRAW_MASK_LINE_SIDE_RIGHT; /*silence compiler*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h index b6ec14f23..b7e4e1cd2 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h @@ -280,7 +280,7 @@ void * lv_draw_mask_remove_custom(void * custom_id); /** * Free the data from the parameter. - * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` + * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` * @param p pointer to a mask parameter diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c index 8cb428824..f34854d9c 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c @@ -38,9 +38,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) { lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t)); dsc->bg_color = lv_color_white(); -#if __STDC_VERSION__ < 201112L dsc->bg_grad.stops[0].color = lv_color_white(); -#endif dsc->bg_grad.stops[1].color = lv_color_black(); dsc->bg_grad.stops[1].frac = 0xFF; dsc->bg_grad.stops_count = 2; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h index efa630cf2..1583e3e67 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h @@ -35,14 +35,8 @@ typedef struct { /*Background*/ lv_opa_t bg_opa; -#if __STDC_VERSION__ >= 201112L - union { -#endif - lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/ - lv_grad_dsc_t bg_grad; -#if __STDC_VERSION__ >= 201112L - }; -#endif + lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/ + lv_grad_dsc_t bg_grad; /*Background img*/ const void * bg_img_src; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c new file mode 100644 index 000000000..580351d6d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c @@ -0,0 +1,54 @@ +/** + * @file lv_draw_transform.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw.h" +#include "lv_draw_transform.h" +#include "../misc/lv_assert.h" +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, + lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +{ + LV_ASSERT_NULL(draw_ctx); + if(draw_ctx->draw_transform == NULL) { + LV_LOG_WARN("draw_ctx->draw_transform == NULL"); + return; + } + + draw_ctx->draw_transform(draw_ctx, dest_area, src_buf, src_w, src_h, src_stride, draw_dsc, cf, cbuf, abuf); + +} + + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h new file mode 100644 index 000000000..1926c2fc2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h @@ -0,0 +1,44 @@ +/** + * @file lv_draw_transform.h + * + */ + +#ifndef LV_DRAW_TRANSFORM_H +#define LV_DRAW_TRANSFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, + lv_coord_t src_w, lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_TRANSFORM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c index a6d0efc36..4c939dd83 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c @@ -54,7 +54,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t uint8_t * buf_u8 = (uint8_t *)dsc->data; if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || - dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || dsc->header.cf == LV_IMG_CF_RGB565A8) { uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; uint32_t px = dsc->header.w * y * px_size + x * px_size; lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t)); @@ -386,6 +386,7 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) case LV_IMG_CF_TRUE_COLOR: return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h); case LV_IMG_CF_TRUE_COLOR_ALPHA: + case LV_IMG_CF_RGB565A8: return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h); case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h); @@ -410,58 +411,6 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) } } -#if LV_DRAW_COMPLEX -/** - * Initialize a descriptor to transform an image - * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized - */ -void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc) -{ - dsc->tmp.pivot_x_256 = dsc->cfg.pivot_x * 256; - dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256; - - int32_t angle_low = dsc->cfg.angle / 10; - int32_t angle_high = angle_low + 1; - int32_t angle_rem = dsc->cfg.angle - (angle_low * 10); - - int32_t s1 = lv_trigo_sin(-angle_low); - int32_t s2 = lv_trigo_sin(-angle_high); - - int32_t c1 = lv_trigo_sin(-angle_low + 90); - int32_t c2 = lv_trigo_sin(-angle_high + 90); - - dsc->tmp.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; - dsc->tmp.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; - - /*Use smaller value to avoid overflow*/ - dsc->tmp.sinma = dsc->tmp.sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - dsc->tmp.cosma = dsc->tmp.cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - - dsc->tmp.chroma_keyed = lv_img_cf_is_chroma_keyed(dsc->cfg.cf) ? 1 : 0; - dsc->tmp.has_alpha = lv_img_cf_has_alpha(dsc->cfg.cf) ? 1 : 0; - if(dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || - dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - dsc->tmp.native_color = 1; - } - else { - dsc->tmp.native_color = 0; - } - - dsc->tmp.img_dsc.data = dsc->cfg.src; - dsc->tmp.img_dsc.header.always_zero = 0; - dsc->tmp.img_dsc.header.cf = dsc->cfg.cf; - dsc->tmp.img_dsc.header.w = dsc->cfg.src_w; - dsc->tmp.img_dsc.header.h = dsc->cfg.src_h; - - /*The inverse of the zoom will be sued during the transformation - * + dsc->cfg.zoom / 2 for rounding*/ - dsc->tmp.zoom_inv = (((256 * 256) << _LV_ZOOM_INV_UPSCALE) + dsc->cfg.zoom / 2) / dsc->cfg.zoom; - - dsc->res.opa = LV_OPA_COVER; - dsc->res.color = dsc->cfg.color; -} -#endif - /** * Get the area of a rectangle if its rotated and scaled * @param res store the coordinates here @@ -483,68 +432,21 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t return; } - res->x1 = (((int32_t)(-pivot->x) * zoom) >> 8) - 1; - res->y1 = (((int32_t)(-pivot->y) * zoom) >> 8) - 1; - res->x2 = (((int32_t)(w - pivot->x) * zoom) >> 8) + 2; - res->y2 = (((int32_t)(h - pivot->y) * zoom) >> 8) + 2; + lv_point_t p[4] = { + {0, 0}, + {w, 0}, + {0, h}, + {w, h}, + }; + lv_point_transform(&p[0], angle, zoom, pivot); + lv_point_transform(&p[1], angle, zoom, pivot); + lv_point_transform(&p[2], angle, zoom, pivot); + lv_point_transform(&p[3], angle, zoom, pivot); + res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x) - 2; + res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) + 2; + res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y) - 2; + res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) + 2; - if(angle == 0) { - res->x1 += pivot->x; - res->y1 += pivot->y; - res->x2 += pivot->x; - res->y2 += pivot->y; - return; - } - - int32_t angle_low = angle / 10; - int32_t angle_high = angle_low + 1; - int32_t angle_rem = angle - (angle_low * 10); - - int32_t s1 = lv_trigo_sin(angle_low); - int32_t s2 = lv_trigo_sin(angle_high); - - int32_t c1 = lv_trigo_sin(angle_low + 90); - int32_t c2 = lv_trigo_sin(angle_high + 90); - - int32_t sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; - int32_t cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; - - /*Use smaller value to avoid overflow*/ - sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - - lv_point_t lt; - lv_point_t rt; - lv_point_t lb; - lv_point_t rb; - - lv_coord_t xt; - lv_coord_t yt; - - xt = res->x1; - yt = res->y1; - lt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; - lt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; - - xt = res->x2; - yt = res->y1; - rt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; - rt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; - - xt = res->x1; - yt = res->y2; - lb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; - lb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; - - xt = res->x2; - yt = res->y2; - rb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; - rb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; - - res->x1 = LV_MIN4(lb.x, lt.x, rb.x, rt.x); - res->x2 = LV_MAX4(lb.x, lt.x, rb.x, rt.x); - res->y1 = LV_MIN4(lb.y, lt.y, rb.y, rt.y); - res->y2 = LV_MAX4(lb.y, lt.y, rb.y, rt.y); #else LV_UNUSED(angle); LV_UNUSED(zoom); @@ -556,217 +458,6 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t #endif } - -#if LV_DRAW_COMPLEX -/** - * Get which color and opa would come to a pixel if it were rotated - * @param dsc a descriptor initialized by `lv_img_buf_rotate_init` - * @param x the coordinate which color and opa should be get - * @param y the coordinate which color and opa should be get - * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image - * @note the result is written back to `dsc->res_color` and `dsc->res_opa` - */ -bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y) -{ - const uint8_t * src_u8 = (const uint8_t *)dsc->cfg.src; - - /*Get the target point relative coordinates to the pivot*/ - int32_t xt = x - dsc->cfg.pivot_x; - int32_t yt = y - dsc->cfg.pivot_y; - - int32_t xs; - int32_t ys; - if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) { - /*Get the source pixel from the upscaled image*/ - xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256; - ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256; - } - else if(dsc->cfg.angle == 0) { - xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE; - yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE; - xs = xt + dsc->tmp.pivot_x_256; - ys = yt + dsc->tmp.pivot_y_256; - } - else { - xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE; - yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE; - xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256; - ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256; - } - - /*Get the integer part of the source pixel*/ - int32_t xs_int = xs >> 8; - int32_t ys_int = ys >> 8; - - if(xs_int >= dsc->cfg.src_w) return false; - else if(xs_int < 0) return false; - - if(ys_int >= dsc->cfg.src_h) return false; - else if(ys_int < 0) return false; - - uint8_t px_size; - uint32_t pxi; - if(dsc->tmp.native_color) { - if(dsc->tmp.has_alpha == 0) { - px_size = LV_COLOR_SIZE >> 3; - - pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; - lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size); - } - else { - px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; - lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1); - dsc->res.opa = src_u8[pxi + px_size - 1]; - } - } - else { - pxi = 0; /*unused*/ - px_size = 0; /*unused*/ - dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color); - dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int); - } - - if(dsc->tmp.chroma_keyed) { - lv_color_t ct = LV_COLOR_CHROMA_KEY; - if(dsc->res.color.full == ct.full) return false; - } - - if(dsc->cfg.antialias == false) return true; - - dsc->tmp.xs = xs; - dsc->tmp.ys = ys; - dsc->tmp.xs_int = xs_int; - dsc->tmp.ys_int = ys_int; - dsc->tmp.pxi = pxi; - dsc->tmp.px_size = px_size; - - bool ret; - ret = _lv_img_buf_transform_anti_alias(dsc); - - return ret; -} - -/** - * Continue transformation by taking the neighbors into account - * @param dsc pointer to the transformation descriptor - */ -bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc) -{ - const uint8_t * src_u8 = dsc->cfg.src; - - /*Get the fractional part of the source pixel*/ - int xs_fract = dsc->tmp.xs & 0xff; - int ys_fract = dsc->tmp.ys & 0xff; - int32_t xn; /*x neighbor*/ - lv_opa_t xr; /*x mix ratio*/ - - if(xs_fract < 0x70) { - xn = - 1; - if(dsc->tmp.xs_int + xn < 0) xn = 0; - xr = xs_fract + 0x80; - } - else if(xs_fract > 0x90) { - xn = 1; - if(dsc->tmp.xs_int + xn >= dsc->cfg.src_w) xn = 0; - xr = (0xFF - xs_fract) + 0x80; - } - else { - xn = 0; - xr = 0xFF; - } - - int32_t yn; /*x neighbor*/ - lv_opa_t yr; /*x mix ratio*/ - - if(ys_fract < 0x70) { - yn = - 1; - if(dsc->tmp.ys_int + yn < 0) yn = 0; - - yr = ys_fract + 0x80; - } - else if(ys_fract > 0x90) { - yn = 1; - if(dsc->tmp.ys_int + yn >= dsc->cfg.src_h) yn = 0; - - yr = (0xFF - ys_fract) + 0x80; - } - else { - yn = 0; - yr = 0xFF; - } - - lv_color_t c00 = dsc->res.color; - lv_color_t c01; - lv_color_t c10; - lv_color_t c11; - - lv_opa_t a00 = dsc->res.opa; - lv_opa_t a10 = 0; - lv_opa_t a01 = 0; - lv_opa_t a11 = 0; - - if(dsc->tmp.native_color) { - lv_memcpy_small(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t)); - lv_memcpy_small(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t)); - lv_memcpy_small(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn], - sizeof(lv_color_t)); - if(dsc->tmp.has_alpha) { - a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1]; - a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1]; - a11 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1]; - } - } - else { - c01 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int, dsc->cfg.color); - c10 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn, dsc->cfg.color); - c11 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn, dsc->cfg.color); - - if(dsc->tmp.has_alpha) { - a10 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int); - a01 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn); - a11 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn); - } - } - - lv_opa_t xr0 = xr; - lv_opa_t xr1 = xr; - if(dsc->tmp.has_alpha) { - lv_opa_t a0 = (a00 * xr + (a10 * (255 - xr))) >> 8; - lv_opa_t a1 = (a01 * xr + (a11 * (255 - xr))) >> 8; - dsc->res.opa = (a0 * yr + (a1 * (255 - yr))) >> 8; - - if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false; - if(a0 <= LV_OPA_MIN) yr = LV_OPA_TRANSP; - if(a1 <= LV_OPA_MIN) yr = LV_OPA_COVER; - if(a00 <= LV_OPA_MIN) xr0 = LV_OPA_TRANSP; - if(a10 <= LV_OPA_MIN) xr0 = LV_OPA_COVER; - if(a01 <= LV_OPA_MIN) xr1 = LV_OPA_TRANSP; - if(a11 <= LV_OPA_MIN) xr1 = LV_OPA_COVER; - } - else { - xr0 = xr; - xr1 = xr; - dsc->res.opa = LV_OPA_COVER; - } - - lv_color_t c0; - if(xr0 == LV_OPA_TRANSP) c0 = c01; - else if(xr0 == LV_OPA_COVER) c0 = c00; - else c0 = lv_color_mix(c00, c01, xr0); - - lv_color_t c1; - if(xr1 == LV_OPA_TRANSP) c1 = c11; - else if(xr1 == LV_OPA_COVER) c1 = c10; - else c1 = lv_color_mix(c10, c11, xr1); - - if(yr == LV_OPA_TRANSP) dsc->res.color = c1; - else if(yr == LV_OPA_COVER) dsc->res.color = c0; - else dsc->res.color = lv_color_mix(c0, c1, yr); - - return true; -} -#endif /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h index 984483e5e..1be7bb652 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h @@ -45,7 +45,6 @@ extern "C" { #define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16) #define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256) -#define _LV_TRANSFORM_TRIGO_SHIFT 10 #define _LV_ZOOM_INV_UPSCALE 5 /********************** @@ -67,16 +66,23 @@ enum { LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels will be transparent*/ - LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/ - LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/ - LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/ - LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/ + LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (can't be chroma keyed)*/ + LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (can't be chroma keyed)*/ + LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (can't be chroma keyed)*/ + LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (can't be chroma keyed)*/ LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/ LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/ LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/ LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/ + LV_IMG_CF_RGB888, + LV_IMG_CF_RGBA8888, + LV_IMG_CF_RGBX8888, + LV_IMG_CF_RGB565, + LV_IMG_CF_RGBA5658, + LV_IMG_CF_RGB565A8, + LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/ LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/ LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/ @@ -138,49 +144,6 @@ typedef struct { const uint8_t * data; /**< Pointer to the data of the image*/ } lv_img_dsc_t; -typedef struct { - struct { - const void * src; /*image source (array of pixels)*/ - lv_coord_t src_w; /*width of the image source*/ - lv_coord_t src_h; /*height of the image source*/ - lv_coord_t pivot_x; /*pivot x*/ - lv_coord_t pivot_y; /*pivot y*/ - int16_t angle; /*angle to rotate*/ - uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/ - lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/ - lv_img_cf_t cf; /*color format of the image to rotate*/ - bool antialias; - } cfg; - - struct { - lv_color_t color; - lv_opa_t opa; - } res; - - struct { - lv_img_dsc_t img_dsc; - int32_t pivot_x_256; - int32_t pivot_y_256; - int32_t sinma; - int32_t cosma; - - uint8_t chroma_keyed : 1; - uint8_t has_alpha : 1; - uint8_t native_color : 1; - - uint32_t zoom_inv; - - /*Runtime data*/ - lv_coord_t xs; - lv_coord_t ys; - lv_coord_t xs_int; - lv_coord_t ys_int; - uint32_t pxi; - uint8_t px_size; - } tmp; -} lv_img_transform_dsc_t; - - /********************** * GLOBAL PROTOTYPES **********************/ @@ -263,30 +226,6 @@ void lv_img_buf_free(lv_img_dsc_t * dsc); */ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); -#if LV_DRAW_COMPLEX -/** - * Initialize a descriptor to rotate an image - * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized - */ -void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc); - -/** - * Continue transformation by taking the neighbors into account - * @param dsc pointer to the transformation descriptor - */ -bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc); - -/** - * Get which color and opa would come to a pixel if it were rotated - * @param dsc a descriptor initialized by `lv_img_buf_rotate_init` - * @param x the coordinate which color and opa should be get - * @param y the coordinate which color and opa should be get - * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image - * @note the result is written back to `dsc->res_color` and `dsc->res_opa` - */ -bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y); - -#endif /** * Get the area of a rectangle if its rotated and scaled * @param res store the coordinates here diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c index 3678a5712..13050b8b7 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c @@ -15,8 +15,8 @@ /********************* * DEFINES *********************/ -#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR -#define CF_BUILT_IN_LAST LV_IMG_CF_ALPHA_8BIT +#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR +#define CF_BUILT_IN_LAST LV_IMG_CF_RGB565A8 /********************** * TYPEDEFS @@ -146,7 +146,7 @@ lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_co dsc->decoder = decoder; res = decoder->open_cb(decoder, dsc); - /*Opened successfully. It is a good decoder to for this image source*/ + /*Opened successfully. It is a good decoder for this image source*/ if(res == LV_RES_OK) return res; /*Prepare for the next loop*/ @@ -361,7 +361,9 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder lv_img_cf_t cf = dsc->header.cf; /*Process true color formats*/ - if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || + cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || cf == LV_IMG_CF_RGB565A8 || + cf == LV_IMG_CF_ALPHA_8BIT) { if(dsc->src_type == LV_IMG_SRC_VARIABLE) { /*In case of uncompressed formats the image stored in the ROM/RAM. *So simply give its pointer*/ @@ -426,8 +428,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder return LV_RES_OK; } /*Alpha indexed images.*/ - else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT || - cf == LV_IMG_CF_ALPHA_8BIT) { + else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT) { return LV_RES_OK; /*Nothing to process*/ } /*Unknown format. Can't decode it.*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h index ebebf1091..f00f95d6a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h @@ -154,8 +154,8 @@ lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header); /** * Open an image. - * Try the created image decoder one by one. Once one is able to open the image that decoder is save in `dsc` - * @param dsc describe a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable. + * Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc` + * @param dsc describes a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable. * @param src the image source. Can be * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`) * 2) Variable: Pointer to an `lv_img_dsc_t` variable diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk new file mode 100644 index 000000000..17371ac98 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk @@ -0,0 +1,9 @@ +CSRCS += lv_gpu_nxp.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp" + +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.c new file mode 100644 index 000000000..46da9334a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.c @@ -0,0 +1,418 @@ +/** + * @file lv_gpu_nxp.c + * + */ + +/** + * MIT License + * + * Copyright 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_gpu_nxp.h" + +#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE + +/* + * allow to use both PXP and VGLITE + + * both 2D accelerators can be used at the same time: + * thus VGLITE can be used to accelerate widget drawing + * while PXP accelerates Blit & Fill operations. + */ +#if LV_USE_GPU_NXP_PXP + #include "pxp/lv_draw_pxp_blend.h" +#endif +#if LV_USE_GPU_NXP_VG_LITE + #include "vglite/lv_draw_vglite_blend.h" + #include "vglite/lv_draw_vglite_rect.h" + #include "vglite/lv_draw_vglite_arc.h" +#endif + +#if LV_COLOR_DEPTH != 32 + #include "../../core/lv_refr.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf); + +static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + +static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + +static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + +static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + uint16_t radius, uint16_t start_angle, uint16_t end_angle); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_nxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + lv_draw_sw_init_ctx(drv, draw_ctx); + + lv_draw_nxp_ctx_t * nxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; + + nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc; + nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect; + nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded; + nxp_draw_ctx->blend = lv_draw_nxp_blend; + //nxp_draw_ctx->base_draw.wait_for_finish = lv_draw_nxp_wait_cb; +} + +void lv_draw_nxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + lv_draw_sw_deinit_ctx(drv, draw_ctx); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * During rendering, LVGL might initializes new draw_ctxs and start drawing into + * a separate buffer (called layer). If the content to be rendered has "holes", + * e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag. + * It means the renderers should draw into an ARGB buffer. + * With 32 bit color depth it's not a big problem but with 16 bit color depth + * the target pixel format is ARGB8565 which is not supported by the GPU. + * In this case, the NXP callbacks should fallback to SW rendering. + */ +static inline bool need_argb8565_support() +{ +#if LV_COLOR_DEPTH != 32 + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + if(disp->driver->screen_transp == 1) + return true; +#endif + + return false; +} + +static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) +{ + lv_area_t blend_area; + + /*Let's get the blend area which is the intersection of the area to fill and the clip area.*/ + if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) + return; /*Fully clipped, nothing to do*/ + + /*Make the blend area relative to the buffer*/ + lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + bool done = false; + + /*Fill/Blend only non masked, normal blended*/ + if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && !need_argb8565_support()) { + lv_color_t * dest_buf = draw_ctx->buf; + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); +#if LV_USE_GPU_NXP_VG_LITE + lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area); + lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area); +#endif + + const lv_color_t * src_buf = dsc->src_buf; + + if(src_buf == NULL) { +#if LV_USE_GPU_NXP_PXP + done = (lv_gpu_nxp_pxp_fill(dest_buf, dest_stride, &blend_area, + dsc->color, dsc->opa) == LV_RES_OK); + if(!done) + PXP_LOG_TRACE("PXP fill failed. Fallback."); + +#endif +#if LV_USE_GPU_NXP_VG_LITE + if(!done) { + done = (lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &blend_area, + dsc->color, dsc->opa) == LV_RES_OK); + if(!done) + VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback."); + } +#endif + } + else { +#if LV_USE_GPU_NXP_PXP + done = (lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, dsc->blend_area, + dsc->opa, LV_DISP_ROT_NONE) == LV_RES_OK); + if(!done) + PXP_LOG_TRACE("PXP blit failed. Fallback."); +#endif +#if LV_USE_GPU_NXP_VG_LITE + if(!done) { + lv_gpu_nxp_vglite_blit_info_t blit; + lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); + + blit.src = src_buf; + blit.src_width = lv_area_get_width(dsc->blend_area); + blit.src_height = lv_area_get_height(dsc->blend_area); + blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t); + blit.src_area.x1 = (blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1)); + blit.src_area.y1 = (blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1)); + blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1; + blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1; + + blit.dst = dest_buf; + blit.dst_width = dest_width; + blit.dst_height = dest_height; + blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t); + blit.dst_area.x1 = blend_area.x1; + blit.dst_area.y1 = blend_area.y1; + blit.dst_area.x2 = blend_area.x2; + blit.dst_area.y2 = blend_area.y2; + + blit.opa = dsc->opa; + blit.zoom = LV_IMG_ZOOM_NONE; + blit.angle = 0; + + done = (lv_gpu_nxp_vglite_blit(&blit) == LV_RES_OK); + + if(!done) + VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback."); + } +#endif + } + } + + if(!done) + lv_draw_sw_blend_basic(draw_ctx, dsc); +} + +static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf) +{ + /*Use the clip area as draw area*/ + lv_area_t draw_area; + lv_area_copy(&draw_area, draw_ctx->clip_area); + bool mask_any = lv_draw_mask_is_any(&draw_area); +#if LV_USE_GPU_NXP_VG_LITE + bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP); +#endif +#if LV_USE_GPU_NXP_PXP + bool scale = (dsc->zoom != LV_IMG_ZOOM_NONE); +#endif + bool done = false; + + lv_area_t blend_area; + /*Let's get the blend area which is the intersection of the area to fill and the clip area.*/ + if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area)) + return; /*Fully clipped, nothing to do*/ + + /*Make the blend area relative to the buffer*/ + lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + const lv_color_t * src_buf = (const lv_color_t *)map_p; + if(!src_buf) { + lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); + return; + } + + lv_color_t * dest_buf = draw_ctx->buf; + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); + +#if LV_USE_GPU_NXP_PXP + if(!mask_any && !scale && !need_argb8565_support() +#if LV_COLOR_DEPTH!=32 + && !lv_img_cf_has_alpha(cf) +#endif + ) { + done = (lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, coords, + dsc, cf) == LV_RES_OK); + if(!done) + PXP_LOG_TRACE("PXP blit transform failed. Fallback."); + } +#endif + +#if LV_USE_GPU_NXP_VG_LITE + if(!done && !mask_any && !need_argb8565_support() && + !lv_img_cf_is_chroma_keyed(cf) && !recolor +#if LV_COLOR_DEPTH!=32 + && !lv_img_cf_has_alpha(cf) +#endif + ) { + lv_gpu_nxp_vglite_blit_info_t blit; + lv_coord_t src_stride = lv_area_get_width(coords); + + blit.src = src_buf; + blit.src_width = lv_area_get_width(coords); + blit.src_height = lv_area_get_height(coords); + blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t); + blit.src_area.x1 = (blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1)); + blit.src_area.y1 = (blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1)); + blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1; + blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1; + + blit.dst = dest_buf; + blit.dst_width = lv_area_get_width(draw_ctx->buf_area); + blit.dst_height = lv_area_get_height(draw_ctx->buf_area); + blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t); + blit.dst_area.x1 = blend_area.x1; + blit.dst_area.y1 = blend_area.y1; + blit.dst_area.x2 = blend_area.x2; + blit.dst_area.y2 = blend_area.y2; + + blit.opa = dsc->opa; + blit.angle = dsc->angle; + blit.pivot = dsc->pivot; + blit.zoom = dsc->zoom; + + done = (lv_gpu_nxp_vglite_blit_transform(&blit) == LV_RES_OK); + + if(!done) + VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback."); + } +#endif + + if(!done) + lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); +} + +static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +{ + bool done = false; + lv_draw_rect_dsc_t nxp_dsc; + + lv_memcpy(&nxp_dsc, dsc, sizeof(nxp_dsc)); +#if LV_DRAW_COMPLEX + /* Draw only the shadow */ + nxp_dsc.bg_opa = 0; + nxp_dsc.bg_img_opa = 0; + nxp_dsc.border_opa = 0; + nxp_dsc.outline_opa = 0; + + lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords); + + /* Draw the background */ + nxp_dsc.shadow_opa = 0; + nxp_dsc.bg_opa = dsc->bg_opa; + done = (draw_nxp_bg(draw_ctx, &nxp_dsc, coords) == LV_RES_OK); +#endif /*LV_DRAW_COMPLEX*/ + + /* Draw the remaining parts */ + nxp_dsc.shadow_opa = 0; + if(done) + nxp_dsc.bg_opa = 0; + nxp_dsc.bg_img_opa = dsc->bg_img_opa; + nxp_dsc.border_opa = dsc->border_opa; + nxp_dsc.outline_opa = dsc->outline_opa; + + lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords); +} + +static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->bg_opa <= LV_OPA_MIN) + return LV_RES_INV; + + lv_area_t bg_coords; + lv_area_copy(&bg_coords, coords); + + /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ + if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) { + bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; + bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; + bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; + bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; + } + + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_ctx->clip_area)) + return LV_RES_INV; + + lv_grad_dir_t grad_dir = dsc->bg_grad.dir; + lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->bg_color : dsc->bg_grad.stops[0].color; + if(bg_color.full == dsc->bg_grad.stops[1].color.full) grad_dir = LV_GRAD_DIR_NONE; + + bool mask_any = lv_draw_mask_is_any(&bg_coords); + + /* + * Most simple case: just a plain rectangle (no mask, no radius, no gradient) + * shall fallback to lv_draw_sw_blend(). + * + * Complex case: gradient or radius but no mask. + */ + if(!mask_any && ((dsc->radius != 0) || (grad_dir != LV_GRAD_DIR_NONE)) && !need_argb8565_support()) { +#if LV_USE_GPU_NXP_VG_LITE + lv_res_t res = lv_gpu_nxp_vglite_draw_bg(draw_ctx, dsc, &bg_coords); + if(res != LV_RES_OK) + VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback."); + + return res; +#endif + } + + return LV_RES_INV; +} + +static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + uint16_t radius, uint16_t start_angle, uint16_t end_angle) +{ + bool done = false; + +#if LV_DRAW_COMPLEX + if(dsc->opa <= LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(start_angle == end_angle) + return; + +#if LV_USE_GPU_NXP_VG_LITE + if(!need_argb8565_support()) { + done = (lv_gpu_nxp_vglite_draw_arc(draw_ctx, dsc, center, (int32_t)radius, + (int32_t)start_angle, (int32_t)end_angle) == LV_RES_OK); + if(!done) + VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback."); + } +#endif +#endif/*LV_DRAW_COMPLEX*/ + + if(!done) + lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle); +} + +#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.h new file mode 100644 index 000000000..899aff25b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_gpu_nxp.h @@ -0,0 +1,71 @@ +/** + * @file lv_gpu_nxp.h + * + */ + +/** + * MIT License + * + * Copyright 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_GPU_NXP_H +#define LV_GPU_NXP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" +#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE +#include "../sw/lv_draw_sw.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef lv_draw_sw_ctx_t lv_draw_nxp_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_nxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_nxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_NXP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk new file mode 100644 index 000000000..ff475a193 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk @@ -0,0 +1,8 @@ +CSRCS += lv_draw_pxp_blend.c +CSRCS += lv_gpu_nxp_pxp_osa.c +CSRCS += lv_gpu_nxp_pxp.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c new file mode 100644 index 000000000..c0a6ecafa --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c @@ -0,0 +1,632 @@ +/** + * @file lv_draw_pxp_blend.c + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_pxp_blend.h" + +#if LV_USE_GPU_NXP_PXP + +/********************* + * DEFINES + *********************/ + +#if LV_COLOR_16_SWAP + #error Color swap not implemented. Disable LV_COLOR_16_SWAP feature. +#endif + +#if LV_COLOR_DEPTH==16 + #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565 + #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565 + #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565 +#elif LV_COLOR_DEPTH==32 + #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888 + #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888 + #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888 +#elif + #error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32. +#endif + +#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \ + || defined (_WIN64) || defined (__LP64__) || defined (__LLP64__) + #define ALIGN_SIZE 8 +#else + #define ALIGN_SIZE 4 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * BLock Image Transfer - copy rectangular image from src buffer to dst buffer + * with combination of transformation (rotation, scale, recolor) and opacity, alpha channel + * or color keying. This requires two steps. First step is used for transformation into + * a temporary buffer and the second one will handle the color format or opacity. + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_area area to be copied from src_buf to dst_buf + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] src_buf source buffer + * @param[in] src_area source area with absolute coordinates to draw on destination buffer + * @param[in] dsc image descriptor + * @param[in] cf color format + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); + +/** + * BLock Image Transfer - copy rectangular image from src buffer to dst buffer + * with transformation and full opacity. + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_area area to be copied from src_buf to dst_buf + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] src_buf source buffer + * @param[in] src_area source area with absolute coordinates to draw on destination buffer + * @param[in] dsc image descriptor + * @param[in] cf color format + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); + +/** + * BLock Image Transfer - copy rectangular image from src buffer to dst buffer + * without transformation but handling color format or opacity. + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_area area to be copied from src_buf to dst_buf + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] src_buf source buffer + * @param[in] src_area source area with absolute coordinates to draw on destination buffer + * @param[in] dsc image descriptor + * @param[in] cf color format + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#define ROUND_UP(x, align) ((x + (align - 1)) & ~(align - 1)) + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, + lv_color_t color, lv_opa_t opa) +{ + uint32_t area_size = lv_area_get_size(fill_area); + lv_coord_t area_w = lv_area_get_width(fill_area); + lv_coord_t area_h = lv_area_get_height(fill_area); + + if(opa >= (lv_opa_t)LV_OPA_MAX) { + if(area_size < LV_GPU_NXP_PXP_FILL_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_SIZE_LIMIT); + return LV_RES_INV; + } + } + else { + if(area_size < LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT); + return LV_RES_INV; + } + } + + PXP_Init(LV_GPU_NXP_PXP_ID); + PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ + + /*OUT buffer configure*/ + pxp_output_buffer_config_t outputConfig = { + .pixelFormat = PXP_OUT_PIXEL_FORMAT, + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * fill_area->y1 + fill_area->x1), + .buffer1Addr = (uint32_t)NULL, + .pitchBytes = dest_stride * sizeof(lv_color_t), + .width = area_w, + .height = area_h + }; + + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig); + + if(opa >= (lv_opa_t)LV_OPA_MAX) { + /*Simple color fill without opacity - AS disabled*/ + PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + + } + else { + /*Fill with opacity - AS used as source (same as OUT)*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = PXP_AS_PIXEL_FORMAT, + .bufferAddr = (uint32_t)outputConfig.buffer0Addr, + .pitchBytes = outputConfig.pitchBytes + }; + + PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, area_w, area_h); + } + + /*Disable PS, use as color generator*/ + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color)); + + /** + * Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff). + * + * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: + * srcFactorMode is actually applied on PS alpha value + * dstFactorMode is actually applied on AS alpha value + */ + pxp_porter_duff_config_t pdConfig = { + .enable = 1, + .dstColorMode = kPXP_PorterDuffColorNoAlpha, + .srcColorMode = kPXP_PorterDuffColorNoAlpha, + .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .dstFactorMode = kPXP_PorterDuffFactorStraight, + .srcFactorMode = (opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed, + .dstGlobalAlpha = opa, + .srcGlobalAlpha = opa, + .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ + .srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/ + }; + + PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); + + lv_gpu_nxp_pxp_run(); /*Start PXP task*/ + + return LV_RES_OK; +} + +lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle) +{ + uint32_t dest_size = lv_area_get_size(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + lv_coord_t dest_h = lv_area_get_height(dest_area); + + if(opa >= (lv_opa_t)LV_OPA_MAX) { + if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT); + return LV_RES_INV; + } + } + else { + if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT); + return LV_RES_INV; + } + } + + PXP_Init(LV_GPU_NXP_PXP_ID); + PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/ + + /* convert rotation angle */ + pxp_rotate_degree_t pxp_rot; + switch(angle) { + case LV_DISP_ROT_NONE: + pxp_rot = kPXP_Rotate0; + break; + case LV_DISP_ROT_90: + pxp_rot = kPXP_Rotate90; + break; + case LV_DISP_ROT_180: + pxp_rot = kPXP_Rotate180; + break; + case LV_DISP_ROT_270: + pxp_rot = kPXP_Rotate270; + break; + default: + pxp_rot = kPXP_Rotate0; + break; + } + PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable); + + pxp_as_blend_config_t asBlendConfig = { + .alpha = opa, + .invertAlpha = false, + .alphaMode = kPXP_AlphaRop, + .ropMode = kPXP_RopMergeAs + }; + + if(opa >= (lv_opa_t)LV_OPA_MAX) { + /*Simple blit, no effect - Disable PS buffer*/ + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + } + else { + pxp_ps_buffer_config_t psBufferConfig = { + .pixelFormat = PXP_PS_PIXEL_FORMAT, + .swapByte = false, + .bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), + .bufferAddrU = 0U, + .bufferAddrV = 0U, + .pitchBytes = dest_stride * sizeof(lv_color_t) + }; + + asBlendConfig.alphaMode = kPXP_AlphaOverride; + + PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig); + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1); + } + + lv_coord_t src_stride = lv_area_get_width(src_area); + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = PXP_AS_PIXEL_FORMAT, + .bufferAddr = (uint32_t)src_buf, + .pitchBytes = src_stride * sizeof(lv_color_t) + }; + PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); + PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); + PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false); + + /*Output buffer.*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride * sizeof(lv_color_t), + .width = dest_w, + .height = dest_h + }; + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); + + lv_gpu_nxp_pxp_run(); /* Start PXP task */ + + return LV_RES_OK; +} + +lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) +{ + uint32_t dest_size = lv_area_get_size(dest_area); + + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { + if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT); + return LV_RES_INV; + } + } + else { + if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) { + PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT); + return LV_RES_INV; + } + } + + bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP); + bool rotation = (dsc->angle != 0); + + if(rotation) { + if(dsc->angle != 0 && dsc->angle != 900 && dsc->angle != 1800 && dsc->angle != 2700) { + PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle); + return LV_RES_INV; + } + } + + if(recolor || rotation) { + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf)) + return lv_gpu_nxp_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf); + else + /*Recolor and/or rotation with alpha or opacity is done in two steps.*/ + return lv_gpu_nxp_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf); + } + + return lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) +{ + lv_coord_t dest_w = lv_area_get_width(dest_area); + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_res_t res; + uint32_t size = dest_w * dest_h * sizeof(lv_color_t); + + if(ROUND_UP(size, ALIGN_SIZE) >= LV_MEM_SIZE) + PXP_RETURN_INV("Insufficient memory for temporary buffer. Please increase LV_MEM_SIZE."); + + lv_color_t * tmp_buf = (lv_color_t *)lv_mem_buf_get(size); + if(!tmp_buf) + PXP_RETURN_INV("Allocating temporary buffer failed."); + + const lv_area_t tmp_area = { + .x1 = 0, + .y1 = 0, + .x2 = dest_w - 1, + .y2 = dest_h - 1 + }; + + /*Step 1: Transform with full opacity to temporary buffer*/ + res = lv_gpu_nxp_pxp_blit_cover(tmp_buf, &tmp_area, dest_w, src_buf, src_area, dsc, cf); + if(res != LV_RES_OK) { + PXP_LOG_TRACE("Blit cover with full opacity failed."); + lv_mem_buf_release(tmp_buf); + + return res; + } + + /*Step 2: Blit temporary results with required opacity to output*/ + res = lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, tmp_buf, &tmp_area, dsc, cf); + + /*Clean-up memory*/ + lv_mem_buf_release(tmp_buf); + + return res; +} + +static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) +{ + lv_coord_t dest_w = lv_area_get_width(dest_area); + lv_coord_t dest_h = lv_area_get_height(dest_area); + + bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP); + bool rotation = (dsc->angle != 0); + + PXP_Init(LV_GPU_NXP_PXP_ID); + PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/ + + if(rotation) { + /* + * PXP is set to process 16x16 blocks to optimize the system for memory + * bandwidth and image processing time. + * The output engine essentially truncates any output pixels after the + * desired number of pixels has been written. + * When rotating a source image and the output is not divisible by the block + * size, the incorrect pixels could be truncated and the final output image + * can look shifted. + */ + if(lv_area_get_width(src_area) % 16 || lv_area_get_height(src_area) % 16) { + PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16."); + return LV_RES_INV; + } + + /*Convert rotation angle*/ + pxp_rotate_degree_t pxp_rot; + switch(dsc->angle) { + case 0: + pxp_rot = kPXP_Rotate0; + break; + case 900: + pxp_rot = kPXP_Rotate90; + break; + case 1800: + pxp_rot = kPXP_Rotate180; + break; + case 2700: + pxp_rot = kPXP_Rotate270; + break; + default: + PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle); + return LV_RES_INV; + } + PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable); + } + + lv_coord_t src_stride = lv_area_get_width(src_area); + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = PXP_AS_PIXEL_FORMAT, + .bufferAddr = (uint32_t)src_buf, + .pitchBytes = src_stride * sizeof(lv_color_t) + }; + PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); + + /*Disable PS buffer*/ + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + if(recolor) + /*Use as color generator*/ + PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor)); + + /*Output buffer*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride * sizeof(lv_color_t), + .width = dest_w, + .height = dest_h + }; + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); + + if(recolor || lv_img_cf_has_alpha(cf)) { + /** + * Configure Porter-Duff blending. + * + * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: + * srcFactorMode is actually applied on PS alpha value + * dstFactorMode is actually applied on AS alpha value + */ + pxp_porter_duff_config_t pdConfig = { + .enable = 1, + .dstColorMode = kPXP_PorterDuffColorWithAlpha, + .srcColorMode = kPXP_PorterDuffColorNoAlpha, + .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha, + .dstFactorMode = kPXP_PorterDuffFactorStraight, + .srcFactorMode = kPXP_PorterDuffFactorInversed, + .dstGlobalAlpha = recolor ? dsc->recolor_opa : 0x00, + .srcGlobalAlpha = 0xff, + .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ + .srcAlphaMode = kPXP_PorterDuffAlphaStraight + }; + PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); + } + + lv_gpu_nxp_pxp_run(); /*Start PXP task*/ + + return LV_RES_OK; +} + +static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, + const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) +{ + lv_coord_t dest_w = lv_area_get_width(dest_area); + lv_coord_t dest_h = lv_area_get_height(dest_area); + + PXP_Init(LV_GPU_NXP_PXP_ID); + PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/ + + pxp_as_blend_config_t asBlendConfig = { + .alpha = dsc->opa, + .invertAlpha = false, + .alphaMode = kPXP_AlphaRop, + .ropMode = kPXP_RopMergeAs + }; + + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_is_chroma_keyed(cf) && !lv_img_cf_has_alpha(cf)) { + /*Simple blit, no effect - Disable PS buffer*/ + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + } + else { + /*PS must be enabled to fetch background pixels. + PS and OUT buffers are the same, blend will be done in-place*/ + pxp_ps_buffer_config_t psBufferConfig = { + .pixelFormat = PXP_PS_PIXEL_FORMAT, + .swapByte = false, + .bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), + .bufferAddrU = 0U, + .bufferAddrV = 0U, + .pitchBytes = dest_stride * sizeof(lv_color_t) + }; + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { + asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaEmbedded : kPXP_AlphaOverride; + } + else { + asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride; + } + PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig); + PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1); + } + + lv_coord_t src_stride = lv_area_get_width(src_area); + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = PXP_AS_PIXEL_FORMAT, + .bufferAddr = (uint32_t)src_buf, + .pitchBytes = src_stride * sizeof(lv_color_t) + }; + PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); + PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); + + if(lv_img_cf_is_chroma_keyed(cf)) { + lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY; + lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY; + + bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP); + + if(recolor) { + /* New color key after recoloring */ + lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa); + + LV_COLOR_SET_R(colorKeyLow, colorKey.ch.red != 0 ? colorKey.ch.red - 1 : 0); + LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0); + LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0); + +#if LV_COLOR_DEPTH==16 + LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f); + LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f); + LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f); +#else /*LV_COLOR_DEPTH==32*/ + LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff); + LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff); + LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff); +#endif + } + + PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_color_to32(colorKeyLow), + lv_color_to32(colorKeyHigh)); + } + + PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_img_cf_is_chroma_keyed(cf)); + + /*Output buffer.*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride * sizeof(lv_color_t), + .width = dest_w, + .height = dest_h + }; + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); + + lv_gpu_nxp_pxp_run(); /* Start PXP task */ + + return LV_RES_OK; +} + +#endif /*LV_USE_GPU_NXP_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h new file mode 100644 index 000000000..43a6440de --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h @@ -0,0 +1,143 @@ +/** + * @file lv_draw_pxp_blend.h + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_DRAW_PXP_BLEND_H +#define LV_DRAW_PXP_BLEND_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_PXP +#include "lv_gpu_nxp_pxp.h" +#include "../../sw/lv_draw_sw.h" + +/********************* + * DEFINES + *********************/ + +#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/ +#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 5000 +#endif + +#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/ +#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 5000 +#endif + +#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT +/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */ +#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 5000 +#endif + +#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/ +#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 5000 +#endif + +#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by PXP with transparency*/ +#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 5000 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Fill area, with optional opacity. + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] fill_area area to fill + * @param[in] color color + * @param[in] opa transparency of the color + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, + lv_color_t color, lv_opa_t opa); + +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. + * By default, image is copied directly, with optional opacity. This function can also + * rotate the display output buffer to a specified angle (90x step). + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_area destination area + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] src_buf source buffer + * @param[in] src_area source area with absolute coordinates to draw on destination buffer + * @param[in] opa opacity of the result + * @param[in] angle display rotation angle (90x) + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle); + +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation. + * + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_area destination area + * @param[in] dest_stride width (stride) of destination buffer in pixels + * @param[in] src_buf source buffer + * @param[in] src_area source area with absolute coordinates to draw on destination buffer + * @param[in] dsc image descriptor + * @param[in] cf color format + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_NXP_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_PXP_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c new file mode 100644 index 000000000..94d242a0d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c @@ -0,0 +1,116 @@ +/** + * @file lv_gpu_nxp_pxp.c + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_gpu_nxp_pxp.h" + +#if LV_USE_GPU_NXP_PXP +#include "lv_gpu_nxp_pxp_osa.h" +#include "../../../core/lv_refr.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * Clean & invalidate cache. + */ +static void invalidate_cache(void); + +/********************** + * STATIC VARIABLES + **********************/ + +static lv_nxp_pxp_cfg_t * pxp_cfg; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_gpu_nxp_pxp_init(void) +{ + pxp_cfg = lv_gpu_nxp_pxp_get_cfg(); + + if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init || !pxp_cfg->pxp_run) + PXP_RETURN_INV("PXP configuration error."); + + PXP_Init(LV_GPU_NXP_PXP_ID); + PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); + + if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) { + PXP_Deinit(LV_GPU_NXP_PXP_ID); + PXP_RETURN_INV("PXP interrupt init failed."); + } + + return LV_RES_OK; +} + +void lv_gpu_nxp_pxp_deinit(void) +{ + pxp_cfg->pxp_interrupt_deinit(); + PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable); + PXP_Deinit(LV_GPU_NXP_PXP_ID); +} + +void lv_gpu_nxp_pxp_run(void) +{ + /*Clean & invalidate cache*/ + invalidate_cache(); + + pxp_cfg->pxp_run(); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void invalidate_cache(void) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + if(disp->driver->clean_dcache_cb) + disp->driver->clean_dcache_cb(disp->driver); +} + +#endif /*LV_USE_GPU_NXP_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h new file mode 100644 index 000000000..e695d8f13 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h @@ -0,0 +1,153 @@ +/** + * @file lv_gpu_nxp_pxp.h + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_GPU_NXP_PXP_H +#define LV_GPU_NXP_PXP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_PXP +#include "fsl_cache.h" +#include "fsl_pxp.h" + +#include "../../../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +/** PXP module instance to use*/ +#define LV_GPU_NXP_PXP_ID PXP + +/** PXP interrupt line ID*/ +#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn + +#ifndef LV_GPU_NXP_PXP_LOG_ERRORS +/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/ +#define LV_GPU_NXP_PXP_LOG_ERRORS 1 +#endif + +#ifndef LV_GPU_NXP_PXP_LOG_TRACES +/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/ +#define LV_GPU_NXP_PXP_LOG_TRACES 0 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/** + * NXP PXP device configuration - call-backs used for + * interrupt init/wait/deinit. + */ +typedef struct { + /** Callback for PXP interrupt initialization*/ + lv_res_t (*pxp_interrupt_init)(void); + + /** Callback for PXP interrupt de-initialization*/ + void (*pxp_interrupt_deinit)(void); + + /** Callback that should start PXP and wait for operation complete*/ + void (*pxp_run)(void); +} lv_nxp_pxp_cfg_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Reset and initialize PXP device. This function should be called as a part + * of display init sequence. + * + * @retval LV_RES_OK PXP init completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_pxp_init(void); + +/** + * Disable PXP device. Should be called during display deinit sequence. + */ +void lv_gpu_nxp_pxp_deinit(void); + +/** + * Start PXP job and wait for completion. + */ +void lv_gpu_nxp_pxp_run(void); + +/********************** + * MACROS + **********************/ + +#define PXP_COND_STOP(cond, txt) \ + do { \ + if (cond) { \ + LV_LOG_ERROR("%s. STOP!", txt); \ + for ( ; ; ); \ + } \ + } while(0) + +#if LV_GPU_NXP_PXP_LOG_ERRORS +#define PXP_RETURN_INV(fmt, ...) \ + do { \ + LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + return LV_RES_INV; \ + } while (0) +#else +#define PXP_RETURN_INV(fmt, ...) \ + do { \ + return LV_RES_INV; \ + }while(0) +#endif /*LV_GPU_NXP_PXP_LOG_ERRORS*/ + +#if LV_GPU_NXP_PXP_LOG_TRACES +#define PXP_LOG_TRACE(fmt, ...) \ + do { \ + LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + } while (0) +#else +#define PXP_LOG_TRACE(fmt, ...) \ + do { \ + } while (0) +#endif /*LV_GPU_NXP_PXP_LOG_TRACES*/ + +#endif /*LV_USE_GPU_NXP_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_NXP_PXP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c similarity index 89% rename from lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c rename to lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c index 1203434c7..c4b8dbe57 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c @@ -6,7 +6,7 @@ /** * MIT License * - * Copyright (c) 2020 NXP + * Copyright 2020, 2022 NXP * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,11 +32,9 @@ *********************/ #include "lv_gpu_nxp_pxp_osa.h" + #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT -#include "../misc/lv_log.h" - - -#include "lv_gpu_nxp_pxp.h" +#include "../../../misc/lv_log.h" #include "fsl_pxp.h" #if defined(SDK_OS_FREE_RTOS) @@ -55,8 +53,20 @@ /********************** * STATIC PROTOTYPES **********************/ + +/** + * PXP interrupt initialization. + */ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void); + +/** + * PXP interrupt de-initialization. + */ static void _lv_gpu_nxp_pxp_interrupt_deinit(void); + +/** + * Start the PXP job and wait for task completion. + */ static void _lv_gpu_nxp_pxp_run(void); /********************** @@ -69,6 +79,12 @@ static void _lv_gpu_nxp_pxp_run(void); static volatile bool s_pxpIdle; #endif +static lv_nxp_pxp_cfg_t pxp_default_cfg = { + .pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init, + .pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit, + .pxp_run = _lv_gpu_nxp_pxp_run +}; + /********************** * MACROS **********************/ @@ -77,9 +93,6 @@ static void _lv_gpu_nxp_pxp_run(void); * GLOBAL FUNCTIONS **********************/ -/** - * PXP device interrupt handler. Used to check PXP task completion status. - */ void PXP_IRQHandler(void) { #if defined(SDK_OS_FREE_RTOS) @@ -94,24 +107,24 @@ void PXP_IRQHandler(void) #else s_pxpIdle = true; #endif - } } +lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void) +{ + return &pxp_default_cfg; +} + /********************** * STATIC FUNCTIONS **********************/ -/** - * PXP interrupt initialization. - */ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) { #if defined(SDK_OS_FREE_RTOS) s_pxpIdle = xSemaphoreCreateBinary(); - if(s_pxpIdle == NULL) { + if(s_pxpIdle == NULL) return LV_RES_INV; - } NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); #else @@ -123,9 +136,6 @@ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) return LV_RES_OK; } -/** - * PXP interrupt de-initialization. - */ static void _lv_gpu_nxp_pxp_interrupt_deinit(void) { NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID); @@ -134,9 +144,6 @@ static void _lv_gpu_nxp_pxp_interrupt_deinit(void) #endif } -/** - * Function to start PXP job. This function must wait for task complete. - */ static void _lv_gpu_nxp_pxp_run(void) { #if !defined(SDK_OS_FREE_RTOS) @@ -147,20 +154,11 @@ static void _lv_gpu_nxp_pxp_run(void) PXP_Start(LV_GPU_NXP_PXP_ID); #if defined(SDK_OS_FREE_RTOS) - if(xSemaphoreTake(s_pxpIdle, portMAX_DELAY) != pdTRUE) { - LV_LOG_ERROR("xSemaphoreTake error. Task halted."); - for(; ;) ; - } + PXP_COND_STOP(!xSemaphoreTake(s_pxpIdle, portMAX_DELAY), "xSemaphoreTake failed."); #else while(s_pxpIdle == false) { } #endif } -lv_nxp_pxp_cfg_t pxp_default_cfg = { - .pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init, - .pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit, - .pxp_run = _lv_gpu_nxp_pxp_run -}; - #endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h similarity index 62% rename from lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h rename to lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h index 89524dae5..5c87824ab 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h @@ -6,7 +6,7 @@ /** * MIT License * - * Copyright (c) 2020 NXP + * Copyright 2020, 2022 NXP * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,21 +27,52 @@ * */ -#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_ -#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_ +#ifndef LV_GPU_NXP_PXP_OSA_H +#define LV_GPU_NXP_PXP_OSA_H #ifdef __cplusplus extern "C" { #endif -#include "../../lv_conf_internal.h" +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT -extern lv_nxp_pxp_cfg_t pxp_default_cfg; -#endif +#include "lv_gpu_nxp_pxp.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * PXP device interrupt handler. Used to check PXP task completion status. + */ +void PXP_IRQHandler(void); + +/** + * Helper function to get the PXP default configuration. + */ +lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/ #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_*/ +#endif /*LV_GPU_NXP_PXP_OSA_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk new file mode 100644 index 000000000..c84e2e47a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk @@ -0,0 +1,9 @@ +CSRCS += lv_draw_vglite_arc.c +CSRCS += lv_draw_vglite_blend.c +CSRCS += lv_draw_vglite_rect.c +CSRCS += lv_gpu_nxp_vglite.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c new file mode 100644 index 000000000..194f03d88 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c @@ -0,0 +1,699 @@ +/** + * @file lv_draw_vglite_arc.c + * + */ + +/** + * MIT License + * + * Copyright 2021, 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite_arc.h" + +#if LV_USE_GPU_NXP_VG_LITE +#include "math.h" + +/********************* + * DEFINES + *********************/ + +#define T_FRACTION 16384.0f + +#define DICHOTO_ITER 5 + +static const uint16_t TperDegree[90] = { + 0, 174, 348, 522, 697, 873, 1049, 1226, 1403, 1581, + 1759, 1938, 2117, 2297, 2477, 2658, 2839, 3020, 3202, 3384, + 3567, 3749, 3933, 4116, 4300, 4484, 4668, 4852, 5037, 5222, + 5407, 5592, 5777, 5962, 6148, 6334, 6519, 6705, 6891, 7077, + 7264, 7450, 7636, 7822, 8008, 8193, 8378, 8564, 8750, 8936, + 9122, 9309, 9495, 9681, 9867, 10052, 10238, 10424, 10609, 10794, + 10979, 11164, 11349, 11534, 11718, 11902, 12086, 12270, 12453, 12637, + 12819, 13002, 13184, 13366, 13547, 13728, 13909, 14089, 14269, 14448, + 14627, 14805, 14983, 15160, 15337, 15513, 15689, 15864, 16038, 16212 +}; + +/********************** + * TYPEDEFS + **********************/ + +/* intermediate arc params */ +typedef struct _vg_arc { + int32_t angle; /* angle <90deg */ + int32_t quarter; /* 0-3 counter-clockwise */ + int32_t rad; /* radius */ + int32_t p0x; /* point P0 */ + int32_t p0y; + int32_t p1x; /* point P1 */ + int32_t p1y; + int32_t p2x; /* point P2 */ + int32_t p2y; + int32_t p3x; /* point P3 */ + int32_t p3y; +} vg_arc; + +typedef struct _cubic_cont_pt { + float p0; + float p1; + float p2; + float p3; +} cubic_cont_pt; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void rotate_point(int32_t angle, int32_t * x, int32_t * y); +static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, + int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + int32_t radius, int32_t start_angle, int32_t end_angle) +{ + + vg_lite_buffer_t vgbuf; + vg_lite_error_t err = VG_LITE_SUCCESS; + lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/ + lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area); + lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area); + vg_lite_path_t path; + vg_lite_color_t vgcol; /* vglite takes ABGR */ + vg_lite_matrix_t matrix; + lv_opa_t opa = dsc->opa; + bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false; + lv_point_t clip_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1}; + + /* path: max size = 16 cubic bezier (7 words each) */ + int32_t arc_path[16 * 7]; + lv_memset_00(arc_path, sizeof(arc_path)); + + /*** Init destination buffer ***/ + if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t), + (const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK) + VG_LITE_RETURN_INV("Init buffer failed."); + + /*** Init path ***/ + lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */ + if(width > (lv_coord_t)radius) + width = radius; + + int pidx = 0; + int32_t cp_x, cp_y; /* control point coords */ + + /* first control point of curve */ + cp_x = radius; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_MOVE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + + /* draw 1-5 outer quarters */ + add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, clip_center, true); + + if(donut) { + /* close outer circle */ + cp_x = radius; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + /* start inner circle */ + cp_x = radius - width; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_MOVE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + + } + else if(dsc->rounded != 0U) { /* 1st rounded arc ending */ + cp_x = radius - width / 2; + cp_y = 0; + rotate_point(end_angle, &cp_x, &cp_y); + lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y}; + add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180), + round_center, true); + + } + else { /* 1st flat ending */ + cp_x = radius - width; + cp_y = 0; + rotate_point(end_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + } + + /* draw 1-5 inner quarters */ + add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, clip_center, false); + + /* last control point of curve */ + if(donut) { /* close the loop */ + cp_x = radius - width; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + + } + else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */ + cp_x = radius - width / 2; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y}; + add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360), + round_center, true); + + } + else { /* 2nd flat ending */ + cp_x = radius; + cp_y = 0; + rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = clip_center.x + cp_x; + arc_path[pidx++] = clip_center.y + cp_y; + } + + arc_path[pidx++] = VLC_OP_END; + + err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path, + (vg_lite_float_t) draw_ctx->clip_area->x1, (vg_lite_float_t) draw_ctx->clip_area->y1, + ((vg_lite_float_t) draw_ctx->clip_area->x2) + 1.0f, ((vg_lite_float_t) draw_ctx->clip_area->y2) + 1.0f); + VG_LITE_ERR_RETURN_INV(err, "Init path failed."); + + /* set rotation angle */ + vg_lite_identity(&matrix); + + if(opa <= (lv_opa_t)LV_OPA_MAX) { + /* Only pre-multiply color if hardware pre-multiplication is not present */ + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { + col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); + col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8); + col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8); + } + col32.ch.alpha = opa; + } + +#if LV_COLOR_DEPTH==16 + vgcol = col32.full; +#else /*LV_COLOR_DEPTH==32*/ + vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) | + (uint32_t)col32.ch.red; +#endif + + /*Clean & invalidate cache*/ + lv_vglite_invalidate_cache(); + + /*** Draw arc ***/ + err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); + VG_LITE_ERR_RETURN_INV(err, "Draw arc failed."); + + err = vg_lite_finish(); + VG_LITE_ERR_RETURN_INV(err, "Finish failed."); + + err = vg_lite_clear_path(&path); + VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); + + return LV_RES_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void copy_arc(vg_arc * dst, vg_arc * src) +{ + dst->quarter = src->quarter; + dst->rad = src->rad; + dst->angle = src->angle; + dst->p0x = src->p0x; + dst->p1x = src->p1x; + dst->p2x = src->p2x; + dst->p3x = src->p3x; + dst->p0y = src->p0y; + dst->p1y = src->p1y; + dst->p2y = src->p2y; + dst->p3y = src->p3y; +} + +/** + * Rotate the point according given rotation angle rotation center is 0,0 + */ +static void rotate_point(int32_t angle, int32_t * x, int32_t * y) +{ + int32_t ori_x = *x; + int32_t ori_y = *y; + int16_t alpha = (int16_t)angle; + *x = ((lv_trigo_cos(alpha) * ori_x) / LV_TRIGO_SIN_MAX) - ((lv_trigo_sin(alpha) * ori_y) / LV_TRIGO_SIN_MAX); + *y = ((lv_trigo_sin(alpha) * ori_x) / LV_TRIGO_SIN_MAX) + ((lv_trigo_cos(alpha) * ori_y) / LV_TRIGO_SIN_MAX); +} + +/** + * Set full arc control points depending on quarter. + * Control points match the best approximation of a circle. + * Arc Quarter position is: + * Q2 | Q3 + * ---+--- + * Q1 | Q0 + */ +static void set_full_arc(vg_arc * fullarc) +{ + /* the tangent lenght for the bezier circle approx */ + float tang = ((float)fullarc->rad) * BEZIER_OPTIM_CIRCLE; + switch(fullarc->quarter) { + case 0: + /* first quarter */ + fullarc->p0x = fullarc->rad; + fullarc->p0y = 0; + fullarc->p1x = fullarc->rad; + fullarc->p1y = (int32_t)tang; + fullarc->p2x = (int32_t)tang; + fullarc->p2y = fullarc->rad; + fullarc->p3x = 0; + fullarc->p3y = fullarc->rad; + break; + case 1: + /* second quarter */ + fullarc->p0x = 0; + fullarc->p0y = fullarc->rad; + fullarc->p1x = 0 - (int32_t)tang; + fullarc->p1y = fullarc->rad; + fullarc->p2x = 0 - fullarc->rad; + fullarc->p2y = (int32_t)tang; + fullarc->p3x = 0 - fullarc->rad; + fullarc->p3y = 0; + break; + case 2: + /* third quarter */ + fullarc->p0x = 0 - fullarc->rad; + fullarc->p0y = 0; + fullarc->p1x = 0 - fullarc->rad; + fullarc->p1y = 0 - (int32_t)tang; + fullarc->p2x = 0 - (int32_t)tang; + fullarc->p2y = 0 - fullarc->rad; + fullarc->p3x = 0; + fullarc->p3y = 0 - fullarc->rad; + break; + case 3: + /* fourth quarter */ + fullarc->p0x = 0; + fullarc->p0y = 0 - fullarc->rad; + fullarc->p1x = (int32_t)tang; + fullarc->p1y = 0 - fullarc->rad; + fullarc->p2x = fullarc->rad; + fullarc->p2y = 0 - (int32_t)tang; + fullarc->p3x = fullarc->rad; + fullarc->p3y = 0; + break; + default: + LV_LOG_ERROR("Invalid arc quarter value."); + break; + } +} + +/** + * Linear interpolation between two points 'a' and 'b' + * 't' parameter is the proportion ratio expressed in range [0 ; T_FRACTION ] + */ +static inline float lerp(float coord_a, float coord_b, uint16_t t) +{ + float tf = (float)t; + return ((T_FRACTION - tf) * coord_a + tf * coord_b) / T_FRACTION; +} + +/** + * Computes a point of bezier curve given 't' param + */ +static inline float comp_bezier_point(float t, cubic_cont_pt cp) +{ + float t_sq = t * t; + float inv_t_sq = (1.0f - t) * (1.0f - t); + float apt = (1.0f - t) * inv_t_sq * cp.p0 + 3.0f * inv_t_sq * t * cp.p1 + 3.0f * (1.0f - t) * t_sq * cp.p2 + t * t_sq * + cp.p3; + return apt; +} + +/** + * Find parameter 't' in curve at point 'pt' + * proceed by dichotomy on only 1 dimension, + * works only if the curve is monotonic + * bezier curve is defined by control points [p0 p1 p2 p3] + * 'dec' tells if curve is decreasing (true) or increasing (false) + */ +static uint16_t get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec) +{ + /* initialize dichotomy with boundary 't' values */ + float t_low = 0.0f; + float t_mid = 0.5f; + float t_hig = 1.0f; + float a_pt; + /* dichotomy loop */ + for(int i = 0; i < DICHOTO_ITER; i++) { + a_pt = comp_bezier_point(t_mid, cp); + /* check mid-point position on bezier curve versus targeted point */ + if((a_pt > pt) != dec) { + t_hig = t_mid; + } + else { + t_low = t_mid; + } + /* define new 't' param for mid-point */ + t_mid = (t_low + t_hig) / 2.0f; + } + /* return parameter 't' in integer range [0 ; T_FRACTION] */ + return (uint16_t)floorf(t_mid * T_FRACTION + 0.5f); +} + +/** + * Gives relative coords of the control points + * for the sub-arc starting at angle with given angle span + */ +static void get_subarc_control_points(vg_arc * arc, int32_t span) +{ + vg_arc fullarc; + fullarc.angle = arc->angle; + fullarc.quarter = arc->quarter; + fullarc.rad = arc->rad; + set_full_arc(&fullarc); + + /* special case of full arc */ + if(arc->angle == 90) { + copy_arc(arc, &fullarc); + return; + } + + /* compute 1st arc using the geometric construction of curve */ + uint16_t t2 = TperDegree[arc->angle + span]; + + /* lerp for A */ + float a2x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t2); + float a2y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t2); + /* lerp for B */ + float b2x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t2); + float b2y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t2); + /* lerp for C */ + float c2x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t2); + float c2y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t2); + + /* lerp for D */ + float d2x = lerp(a2x, b2x, t2); + float d2y = lerp(a2y, b2y, t2); + /* lerp for E */ + float e2x = lerp(b2x, c2x, t2); + float e2y = lerp(b2y, c2y, t2); + + float pt2x = lerp(d2x, e2x, t2); + float pt2y = lerp(d2y, e2y, t2); + + /* compute sub-arc using the geometric construction of curve */ + uint16_t t1 = TperDegree[arc->angle]; + + /* lerp for A */ + float a1x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t1); + float a1y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t1); + /* lerp for B */ + float b1x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t1); + float b1y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t1); + /* lerp for C */ + float c1x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t1); + float c1y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t1); + + /* lerp for D */ + float d1x = lerp(a1x, b1x, t1); + float d1y = lerp(a1y, b1y, t1); + /* lerp for E */ + float e1x = lerp(b1x, c1x, t1); + float e1y = lerp(b1y, c1y, t1); + + float pt1x = lerp(d1x, e1x, t1); + float pt1y = lerp(d1y, e1y, t1); + + /* find the 't3' parameter for point P(t1) on the sub-arc [P0 A2 D2 P(t2)] using dichotomy + * use position of x axis only */ + uint16_t t3; + t3 = get_bez_t_from_pos(pt1x, + (cubic_cont_pt) { + .p0 = ((float)fullarc.p0x), .p1 = a2x, .p2 = d2x, .p3 = pt2x + }, + (bool)(pt2x < (float)fullarc.p0x)); + + /* lerp for B */ + float b3x = lerp(a2x, d2x, t3); + float b3y = lerp(a2y, d2y, t3); + /* lerp for C */ + float c3x = lerp(d2x, pt2x, t3); + float c3y = lerp(d2y, pt2y, t3); + + /* lerp for E */ + float e3x = lerp(b3x, c3x, t3); + float e3y = lerp(b3y, c3y, t3); + + arc->p0x = (int32_t)floorf(0.5f + pt1x); + arc->p0y = (int32_t)floorf(0.5f + pt1y); + arc->p1x = (int32_t)floorf(0.5f + e3x); + arc->p1y = (int32_t)floorf(0.5f + e3y); + arc->p2x = (int32_t)floorf(0.5f + c3x); + arc->p2y = (int32_t)floorf(0.5f + c3y); + arc->p3x = (int32_t)floorf(0.5f + pt2x); + arc->p3y = (int32_t)floorf(0.5f + pt2y); +} + +/** + * Gives relative coords of the control points + */ +static void get_arc_control_points(vg_arc * arc, bool start) +{ + vg_arc fullarc; + fullarc.angle = arc->angle; + fullarc.quarter = arc->quarter; + fullarc.rad = arc->rad; + set_full_arc(&fullarc); + + /* special case of full arc */ + if(arc->angle == 90) { + copy_arc(arc, &fullarc); + return; + } + + /* compute sub-arc using the geometric construction of curve */ + uint16_t t = TperDegree[arc->angle]; + /* lerp for A */ + float ax = lerp((float)fullarc.p0x, (float)fullarc.p1x, t); + float ay = lerp((float)fullarc.p0y, (float)fullarc.p1y, t); + /* lerp for B */ + float bx = lerp((float)fullarc.p1x, (float)fullarc.p2x, t); + float by = lerp((float)fullarc.p1y, (float)fullarc.p2y, t); + /* lerp for C */ + float cx = lerp((float)fullarc.p2x, (float)fullarc.p3x, t); + float cy = lerp((float)fullarc.p2y, (float)fullarc.p3y, t); + + /* lerp for D */ + float dx = lerp(ax, bx, t); + float dy = lerp(ay, by, t); + /* lerp for E */ + float ex = lerp(bx, cx, t); + float ey = lerp(by, cy, t); + + /* sub-arc's control points are tangents of DeCasteljau's algorithm */ + if(start) { + arc->p0x = (int32_t)floorf(0.5f + lerp(dx, ex, t)); + arc->p0y = (int32_t)floorf(0.5f + lerp(dy, ey, t)); + arc->p1x = (int32_t)floorf(0.5f + ex); + arc->p1y = (int32_t)floorf(0.5f + ey); + arc->p2x = (int32_t)floorf(0.5f + cx); + arc->p2y = (int32_t)floorf(0.5f + cy); + arc->p3x = fullarc.p3x; + arc->p3y = fullarc.p3y; + } + else { + arc->p0x = fullarc.p0x; + arc->p0y = fullarc.p0y; + arc->p1x = (int32_t)floorf(0.5f + ax); + arc->p1y = (int32_t)floorf(0.5f + ay); + arc->p2x = (int32_t)floorf(0.5f + dx); + arc->p2y = (int32_t)floorf(0.5f + dy); + arc->p3x = (int32_t)floorf(0.5f + lerp(dx, ex, t)); + arc->p3y = (int32_t)floorf(0.5f + lerp(dy, ey, t)); + } +} + +/** + * Add the arc control points into the path data for vglite, + * taking into account the real center of the arc (translation). + * arc_path: (in/out) the path data array for vglite + * pidx: (in/out) index of last element added in arc_path + * q_arc: (in) the arc data containing control points + * center: (in) the center of the circle in draw coordinates + * cw: (in) true if arc is clockwise + */ +static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, lv_point_t center, bool cw) +{ + /* assumes first control point already in array arc_path[] */ + int idx = *pidx; + if(cw) { +#if BEZIER_DBG_CONTROL_POINTS + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p1x + center.x; + arc_path[idx++] = q_arc->p1y + center.y; + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p2x + center.x; + arc_path[idx++] = q_arc->p2y + center.y; + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p3x + center.x; + arc_path[idx++] = q_arc->p3y + center.y; +#else + arc_path[idx++] = VLC_OP_CUBIC; + arc_path[idx++] = q_arc->p1x + center.x; + arc_path[idx++] = q_arc->p1y + center.y; + arc_path[idx++] = q_arc->p2x + center.x; + arc_path[idx++] = q_arc->p2y + center.y; + arc_path[idx++] = q_arc->p3x + center.x; + arc_path[idx++] = q_arc->p3y + center.y; +#endif + } + else { /* reverse points order when counter-clockwise */ +#if BEZIER_DBG_CONTROL_POINTS + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p2x + center.x; + arc_path[idx++] = q_arc->p2y + center.y; + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p1x + center.x; + arc_path[idx++] = q_arc->p1y + center.y; + arc_path[idx++] = VLC_OP_LINE; + arc_path[idx++] = q_arc->p0x + center.x; + arc_path[idx++] = q_arc->p0y + center.y; +#else + arc_path[idx++] = VLC_OP_CUBIC; + arc_path[idx++] = q_arc->p2x + center.x; + arc_path[idx++] = q_arc->p2y + center.y; + arc_path[idx++] = q_arc->p1x + center.x; + arc_path[idx++] = q_arc->p1y + center.y; + arc_path[idx++] = q_arc->p0x + center.x; + arc_path[idx++] = q_arc->p0y + center.y; +#endif + } + /* update index i n path array*/ + *pidx = idx; +} + +static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, + int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw) +{ + /* set number of arcs to draw */ + vg_arc q_arc; + int32_t start_arc_angle = start_angle % 90; + int32_t end_arc_angle = end_angle % 90; + int32_t inv_start_arc_angle = (start_arc_angle > 0) ? (90 - start_arc_angle) : 0; + int32_t nbarc = (end_angle - start_angle - inv_start_arc_angle - end_arc_angle) / 90; + q_arc.rad = radius; + + /* handle special case of start & end point in the same quarter */ + if(((start_angle / 90) == (end_angle / 90)) && (nbarc <= 0)) { + q_arc.quarter = (start_angle / 90) % 4; + q_arc.angle = start_arc_angle; + get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle); + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + return; + } + + if(cw) { + /* partial starting arc */ + if(start_arc_angle > 0) { + q_arc.quarter = (start_angle / 90) % 4; + q_arc.angle = start_arc_angle; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, true); + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + /* full arcs */ + for(int32_t q = 0; q < nbarc ; q++) { + q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4; + q_arc.angle = 90; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + /* partial ending arc */ + if(end_arc_angle > 0) { + q_arc.quarter = (end_angle / 90) % 4; + q_arc.angle = end_arc_angle; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, false); + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + + } + else { /* counter clockwise */ + + /* partial ending arc */ + if(end_arc_angle > 0) { + q_arc.quarter = (end_angle / 90) % 4; + q_arc.angle = end_arc_angle; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, false); + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + /* full arcs */ + for(int32_t q = nbarc - 1; q >= 0; q--) { + q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4; + q_arc.angle = 90; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + /* partial starting arc */ + if(start_arc_angle > 0) { + q_arc.quarter = (start_angle / 90) % 4; + q_arc.angle = start_arc_angle; + /* get cubic points relative to center */ + get_arc_control_points(&q_arc, true); + /* put cubic points in arc_path */ + add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + } + } +} + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h new file mode 100644 index 000000000..98ba8a3d0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h @@ -0,0 +1,79 @@ +/** + * @file lv_draw_vglite_arc.h + * + */ + +/** + * MIT License + * + * Copyright 2021, 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_DRAW_VGLITE_ARC_H +#define LV_DRAW_VGLITE_ARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_VG_LITE +#include "lv_gpu_nxp_vglite.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*** + * Draw arc shape with effects + * @param draw_ctx drawing context + * @param dsc the arc description structure (width, rounded ending, opacity) + * @param center the coordinates of the arc center + * @param radius the radius of external arc + * @param start_angle the starting angle in degrees + * @param end_angle the ending angle in degrees + */ +lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + int32_t radius, int32_t start_angle, int32_t end_angle); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_VGLITE_ARC_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c new file mode 100644 index 000000000..b59b143b3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c @@ -0,0 +1,618 @@ +/** + * @file lv_draw_vglite_blend.c + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite_blend.h" + +#if LV_USE_GPU_NXP_VG_LITE + +/********************* + * DEFINES + *********************/ + +/* Enable BLIT quality degradation workaround for RT595, recommended for screen's dimension > 352 pixels */ +#define RT595_BLIT_WRKRND_ENABLED 1 + +/* Internal compound symbol */ +#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ + defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ + RT595_BLIT_WRKRND_ENABLED +#define VG_LITE_BLIT_SPLIT_ENABLED 1 +#else +#define VG_LITE_BLIT_SPLIT_ENABLED 0 +#endif + +/** + * BLIT split threshold - BLITs with width or height higher than this value will be done + * in multiple steps. Value must be 16-aligned. Don't change. + */ +#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352 + + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * BLock Image Transfer - single direct BLIT. + * + * @param[in] blit Description of the transfer + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit); + +#if VG_LITE_BLIT_SPLIT_ENABLED + + /** + * Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only. + * + * @param[in,out] area Area to be updated + * @param[in,out] buf Pointer to be updated + */ + static void _align_x(lv_area_t * area, lv_color_t ** buf); + + /** + * Move buffer pointer to the area start and update variables, Y-axis only. + * + * @param[in,out] area Area to be updated + * @param[in,out] buf Pointer to be updated + * @param[in] stridePx Buffer stride in pixels + */ + static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx); + + /** + * Software BLIT as a fall-back scenario. + * + * @param[in] blit BLIT configuration + */ + static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit); + + /** + * Verify BLIT structure - widths, stride, pointer alignment + * + * @param[in] blit BLIT configuration + * @retval LV_RES_OK + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ + static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit); + + /** + * BLock Image Transfer - split BLIT. + * + * @param[in] blit BLIT configuration + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ + static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa) +{ + uint32_t area_size = lv_area_get_size(fill_area); + lv_coord_t area_w = lv_area_get_width(fill_area); + lv_coord_t area_h = lv_area_get_height(fill_area); + + if(opa >= (lv_opa_t)LV_OPA_MAX) { + if(area_size < LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT); + } + else { + if(area_size < LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT); + } + + vg_lite_buffer_t vgbuf; + vg_lite_rectangle_t rect; + vg_lite_error_t err = VG_LITE_SUCCESS; + lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ + vg_lite_color_t vgcol; /* vglite takes ABGR */ + + if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t), + (const lv_color_t *)dest_buf, false) != LV_RES_OK) + VG_LITE_RETURN_INV("Init buffer failed."); + + if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/ + rect.x = fill_area->x1; + rect.y = fill_area->y1; + rect.width = area_w; + rect.height = area_h; + + /*Clean & invalidate cache*/ + lv_vglite_invalidate_cache(); + +#if LV_COLOR_DEPTH==16 + vgcol = col32.full; +#else /*LV_COLOR_DEPTH==32*/ + vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) | + (uint32_t)col32.ch.red; +#endif + + err = vg_lite_clear(&vgbuf, &rect, vgcol); + VG_LITE_ERR_RETURN_INV(err, "Clear failed."); + + err = vg_lite_finish(); + VG_LITE_ERR_RETURN_INV(err, "Finish failed."); + } + else { /*fill with transparency*/ + + vg_lite_path_t path; + int32_t path_data[] = { /*VG rectangular path*/ + VLC_OP_MOVE, fill_area->x1, fill_area->y1, + VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1, + VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1, + VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1, + VLC_OP_LINE, fill_area->x1, fill_area->y1, + VLC_OP_END + }; + + err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data, + (vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, + ((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f); + VG_LITE_ERR_RETURN_INV(err, "Init path failed."); + + /* Only pre-multiply color if hardware pre-multiplication is not present */ + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { + col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); + col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8); + col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8); + } + col32.ch.alpha = opa; + +#if LV_COLOR_DEPTH==16 + vgcol = col32.full; +#else /*LV_COLOR_DEPTH==32*/ + vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) | + (uint32_t)col32.ch.red; +#endif + + /*Clean & invalidate cache*/ + lv_vglite_invalidate_cache(); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /*Draw rectangle*/ + err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); + VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed."); + + err = vg_lite_finish(); + VG_LITE_ERR_RETURN_INV(err, "Finish failed."); + + err = vg_lite_clear_path(&path); + VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); + } + + return LV_RES_OK; +} + +lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + uint32_t dest_size = lv_area_get_size(&blit->dst_area); + + if(blit->opa >= (lv_opa_t)LV_OPA_MAX) { + if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT); + } + else { + if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT); + } + +#if VG_LITE_BLIT_SPLIT_ENABLED + return _lv_gpu_nxp_vglite_blit_split(blit); +#endif /* non RT595 */ + + /* Just pass down */ + return _lv_gpu_nxp_vglite_blit_single(blit); +} + +lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + uint32_t dest_size = lv_area_get_size(&blit->dst_area); + + if(blit->opa >= (lv_opa_t)LV_OPA_MAX) { + if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT); + } + else { + if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT) + VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT); + } + + return _lv_gpu_nxp_vglite_blit_single(blit); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#if VG_LITE_BLIT_SPLIT_ENABLED +static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + lv_res_t rv = LV_RES_INV; + + if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) { + PRINT_BLT("Blit check failed\n"); + return LV_RES_INV; + } + + PRINT_BLT("BLIT from: " + "Area: %03d,%03d - %03d,%03d " + "Addr: %d\n\n", + blit->src_area.x1, blit->src_area.y1, + blit->src_area.x2, blit->src_area.y2, + (uintptr_t) blit->src); + + PRINT_BLT("BLIT to: " + "Area: %03d,%03d - %03d,%03d " + "Addr: %d\n\n", + blit->dst_area.x1, blit->dst_area.y1, + blit->dst_area.x2, blit->dst_area.y2, + (uintptr_t) blit->src); + + /* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */ + _align_x(&blit->src_area, (lv_color_t **)&blit->src); + _align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t)); + _align_x(&blit->dst_area, (lv_color_t **)&blit->dst); + _align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t)); + + /* Stage 2: If we're in limit, do a single BLIT */ + if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) && + (blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) { + PRINT_BLT("Simple blit!\n"); + return _lv_gpu_nxp_vglite_blit_single(blit); + }; + + /* Stage 3: Split the BLIT into multiple tiles */ + PRINT_BLT("Split blit!\n"); + + PRINT_BLT("Blit " + "([%03d,%03d], [%03d,%03d]) -> " + "([%03d,%03d], [%03d,%03d]) | " + "([%03dx%03d] -> [%03dx%03d]) | " + "A:(%d -> %d)\n", + blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2, + blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2, + lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area), + lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area), + (uintptr_t) blit->src, (uintptr_t) blit->dst); + + + lv_coord_t totalWidth = lv_area_get_width(&blit->src_area); + lv_coord_t totalHeight = lv_area_get_height(&blit->src_area); + + lv_gpu_nxp_vglite_blit_info_t tileBlit; + + /* Number of tiles needed */ + int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + + /* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as + * the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be + * different */ + int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0; + int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0; + + PRINT_BLT("\n"); + PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX); + + tileBlit = *blit; + + for(int tileY = 0; tileY < totalTilesY; tileY++) { + + tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */ + tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */ + } + tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof( + lv_color_t); /* stride in px! */ + + tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */ + tileBlit.dst_area.y2 = tileBlit.src_area.y2; + + tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof( + lv_color_t); /* stride in px! */ + + for(int tileX = 0; tileX < totalTilesX; tileX++) { + + if(tileX == 0) { + /* 1st tile is special - there may be a gap between buffer start pointer + * and area.x1 value, as the pointer has to be aligned. + * tileBlit.src pointer - keep init value from Y-loop. + * Also, 1st tile start is not shifted! shift is applied from 2nd tile */ + tileBlit.src_area.x1 = blit->src_area.x1; + tileBlit.dst_area.x1 = blit->dst_area.x1; + } + else { + /* subsequent tiles always starts from 0, but shifted*/ + tileBlit.src_area.x1 = 0 + shiftSrcX; + tileBlit.dst_area.x1 = 0 + shiftDstX; + /* and advance start pointer + 1 tile size */ + tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + } + + /* Clip tile end coordinates */ + tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + } + + tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + } + + if(tileX < (totalTilesX - 1)) { + /* And adjust end coords if shifted, but not for last tile! */ + tileBlit.src_area.x2 += shiftSrcX; + tileBlit.dst_area.x2 += shiftDstX; + } + + rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit); + +#if BLIT_DBG_AREAS + lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area, + LV_COLOR_RED); + lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area, + LV_COLOR_GREEN); +#endif + + PRINT_BLT("Tile [%d, %d]: " + "([%d,%d], [%d,%d]) -> " + "([%d,%d], [%d,%d]) | " + "([%dx%d] -> [%dx%d]) | " + "A:(0x%8X -> 0x%8X) %s\n", + tileX, tileY, + tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2, + tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2, + lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area), + lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area), + (uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst, + rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!"); + + if(rv != LV_RES_OK) { /* if anything goes wrong... */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("Split blit failed. Trying SW blit instead."); +#endif + _sw_blit(&tileBlit); + rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */ + } + + } + PRINT_BLT(" \n"); + } + + return rv; /* should never fail */ +} +#endif /* VG_LITE_BLIT_SPLIT_ENABLED */ + +static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + vg_lite_buffer_t src_vgbuf, dst_vgbuf; + vg_lite_error_t err = VG_LITE_SUCCESS; + uint32_t rect[4]; + vg_lite_float_t scale = 1.0; + + if(blit == NULL) { + /*Wrong parameter*/ + return LV_RES_INV; + } + + if(blit->opa < (lv_opa_t) LV_OPA_MIN) { + return LV_RES_OK; /*Nothing to BLIT*/ + } + + /*Wrap src/dst buffer into VG-Lite buffer*/ + if(lv_vglite_init_buf(&src_vgbuf, (uint32_t)blit->src_width, (uint32_t)blit->src_height, (uint32_t)blit->src_stride, + blit->src, true) != LV_RES_OK) + VG_LITE_RETURN_INV("Init buffer failed."); + + if(lv_vglite_init_buf(&dst_vgbuf, (uint32_t)blit->dst_width, (uint32_t)blit->dst_height, (uint32_t)blit->dst_stride, + blit->dst, false) != LV_RES_OK) + VG_LITE_RETURN_INV("Init buffer failed."); + + rect[0] = (uint32_t)blit->src_area.x1; /* start x */ + rect[1] = (uint32_t)blit->src_area.y1; /* start y */ + rect[2] = (uint32_t)blit->src_area.x2 - (uint32_t)blit->src_area.x1 + 1U; /* width */ + rect[3] = (uint32_t)blit->src_area.y2 - (uint32_t)blit->src_area.y1 + 1U; /* height */ + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix); + + if((blit->angle != 0) || (blit->zoom != LV_IMG_ZOOM_NONE)) { + vg_lite_translate(blit->pivot.x, blit->pivot.y, &matrix); + vg_lite_rotate(blit->angle / 10.0f, &matrix); /* angle is 1/10 degree */ + scale = 1.0f * blit->zoom / LV_IMG_ZOOM_NONE; + vg_lite_scale(scale, scale, &matrix); + vg_lite_translate(0.0f - blit->pivot.x, 0.0f - blit->pivot.y, &matrix); + } + + /*Clean & invalidate cache*/ + lv_vglite_invalidate_cache(); + + uint32_t color; + vg_lite_blend_t blend; + if(blit->opa >= (lv_opa_t)LV_OPA_MAX) { + color = 0xFFFFFFFFU; + blend = VG_LITE_BLEND_SRC_OVER; + src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT; + } + else { + uint32_t opa = (uint32_t)blit->opa; + if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { + color = (opa << 24) | 0x00FFFFFFU; + } + else { + color = (opa << 24) | (opa << 16) | (opa << 8) | opa; + } + blend = VG_LITE_BLEND_SRC_OVER; + src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT; + } + + err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); + VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed."); + + err = vg_lite_finish(); + VG_LITE_ERR_RETURN_INV(err, "Finish failed."); + + return LV_RES_OK; +} + +#if VG_LITE_BLIT_SPLIT_ENABLED + +static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + int x, y; + + lv_coord_t w = lv_area_get_width(&blit->src_area); + lv_coord_t h = lv_area_get_height(&blit->src_area); + + int32_t srcStridePx = blit->src_stride / (int32_t)sizeof(lv_color_t); + int32_t dstStridePx = blit->dst_stride / (int32_t)sizeof(lv_color_t); + + lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1; + lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1; + + if(blit->opa >= (lv_opa_t)LV_OPA_MAX) { + /* simple copy */ + for(y = 0; y < h; y++) { + lv_memcpy(dst, src, (uint32_t)w * sizeof(lv_color_t)); + src += srcStridePx; + dst += dstStridePx; + } + } + else if(blit->opa >= LV_OPA_MIN) { + /* alpha blending */ + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dst[x] = lv_color_mix(src[x], dst[x], blit->opa); + } + src += srcStridePx; + dst += dstStridePx; + } + } +} + +static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + + /* Test for minimal width */ + if(lv_area_get_width(&blit->src_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) + VG_LITE_RETURN_INV("Src area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + + /* Test for minimal width */ + if(lv_area_get_width(&blit->dst_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) + VG_LITE_RETURN_INV("Dest area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + + /* Test for pointer alignment */ + if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) + VG_LITE_RETURN_INV("Src buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE); + + /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ + + /* Test for stride alignment */ + if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) + VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.", blit->src_stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + + /* Test for stride alignment */ + if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) + VG_LITE_RETURN_INV("Dest buffer stride (%d px) not aligned to %d px.", blit->dst_stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + + if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) || + (lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area))) + VG_LITE_RETURN_INV("Src and dest buffer areas are not equal."); + + return LV_RES_OK; +} + +static void _align_x(lv_area_t * area, lv_color_t ** buf) +{ + + int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH)); + VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment."); + + area->x1 -= alignedAreaStartPx; + area->x2 -= alignedAreaStartPx; + *buf += alignedAreaStartPx; +} + +static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx) +{ + int LineToAlignMem; + int alignedAreaStartPy; + /* find how many lines of pixels will respect memory alignment requirement */ + if(stridePx % (uint32_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0U) { + alignedAreaStartPy = area->y1; + } + else { + LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX), + "Complex case: need gcd function."); + alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); + VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment."); + } + + area->y1 -= alignedAreaStartPy; + area->y2 -= alignedAreaStartPy; + *buf += (uint32_t)alignedAreaStartPy * stridePx; +} +#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h similarity index 74% rename from lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h rename to lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h index 26f4c3fe4..bc448c65a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h @@ -1,12 +1,12 @@ /** - * @file lv_gpu_nxp_vglite.h + * @file lv_draw_vglite_blend.h * */ /** * MIT License * - * Copyright (c) 2020 NXP + * Copyright 2020-2022 NXP * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,8 +27,8 @@ * */ -#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_ -#define LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_ +#ifndef LV_DRAW_VGLITE_BLEND_H +#define LV_DRAW_VGLITE_BLEND_H #ifdef __cplusplus extern "C" { @@ -37,48 +37,39 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../lv_conf_internal.h" + +#include "../../../lv_conf_internal.h" #if LV_USE_GPU_NXP_VG_LITE +#include "lv_gpu_nxp_vglite.h" /********************* * DEFINES *********************/ -/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */ -#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1) - -/** Stride in px required by VG-Lite HW. Don't change this. */ -#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U - #ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT /** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/ -#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 32 +#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 5000 #endif #ifndef LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT /** Minimum area (in pixels) to be filled by VG-Lite with transparency*/ -#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 32 +#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 5000 #endif #ifndef LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT /** Minimum area (in pixels) for image copy with 100% opacity to be handled by VG-Lite*/ -#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 32 +#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 5000 #endif #ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT /** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */ -#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 32 +#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 5000 #endif #ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT /** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/ -#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 32 -#endif - -#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS -/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/ -#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1 +#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 5000 #endif /********************** @@ -94,30 +85,29 @@ typedef struct { lv_area_t src_area; /**< Area to be copied from source*/ lv_coord_t src_width; /**< Source buffer width*/ lv_coord_t src_height; /**< Source buffer height*/ - uint32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/ + int32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/ const lv_color_t * dst; /**< Destination buffer pointer (must be aligned on 32 bytes)*/ lv_area_t dst_area; /**< Target area in destination buffer (must be the same as src_area)*/ lv_coord_t dst_width; /**< Destination buffer width*/ lv_coord_t dst_height; /**< Destination buffer height*/ - uint32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/ + int32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/ lv_opa_t opa; /**< Opacity - alpha mix (0 = source not copied, 255 = 100% opaque)*/ - + uint32_t angle; /**< Rotation angle (1/10 of degree)*/ + uint32_t zoom; /**< 256 = no zoom (1:1 scale ratio)*/ + lv_point_t pivot; /**< The coordinates of rotation pivot in source image buffer*/ } lv_gpu_nxp_vglite_blit_info_t; /********************** - * MACROS + * GLOBAL PROTOTYPES **********************/ -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/*** - * Fills rectangular area in buffer. - * @param[in] dest_buf Destination buffer pointer (must be aligned on 32 bytes) - * @param[in] dest_width Destination buffer width in pixels ((must be aligned on 16 px) +/** + * Fill area, with optional opacity. + * + * @param[in/out] dest_buf Destination buffer pointer (must be aligned on 32 bytes) + * @param[in] dest_width Destination buffer width in pixels (must be aligned on 16 px) * @param[in] dest_height Destination buffer height in pixels * @param[in] fill_area Area to be filled * @param[in] color Fill color @@ -128,18 +118,32 @@ typedef struct { lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa); -/*** +/** * BLock Image Transfer. + * * @param[in] blit Description of the transfer * @retval LV_RES_OK Transfer complete * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit); +/** + * BLock Image Transfer with transformation. + * + * @param[in] blit Description of the transfer + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit); + +/********************** + * MACROS + **********************/ + #endif /*LV_USE_GPU_NXP_VG_LITE*/ #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_*/ +#endif /*LV_DRAW_VGLITE_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c new file mode 100644 index 000000000..bc1d55c85 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c @@ -0,0 +1,244 @@ +/** + * @file lv_draw_vglite_rect.c + * + */ + +/** + * MIT License + * + * Copyright 2021, 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite_rect.h" + +#if LV_USE_GPU_NXP_VG_LITE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +{ + vg_lite_buffer_t vgbuf; + vg_lite_error_t err = VG_LITE_SUCCESS; + lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area); + lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area); + vg_lite_path_t path; + vg_lite_color_t vgcol; /* vglite takes ABGR */ + vg_lite_matrix_t matrix; + lv_coord_t width = lv_area_get_width(coords); + lv_coord_t height = lv_area_get_height(coords); + vg_lite_linear_gradient_t gradient; + vg_lite_matrix_t * grad_matrix; + + if(dsc->radius < 0) + return LV_RES_INV; + + /* Make areas relative to draw buffer */ + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + lv_area_t rel_clip; + lv_area_copy(&rel_clip, draw_ctx->clip_area); + lv_area_move(&rel_clip, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + /*** Init destination buffer ***/ + if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t), + (const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK) + VG_LITE_RETURN_INV("Init buffer failed."); + + /*** Init path ***/ + int32_t rad = dsc->radius; + if(dsc->radius == LV_RADIUS_CIRCLE) { + rad = (width > height) ? height / 2 : width / 2; + } + + if((dsc->radius == LV_RADIUS_CIRCLE) && (width == height)) { + float tang = ((float)rad * BEZIER_OPTIM_CIRCLE); + int32_t cpoff = (int32_t)tang; + int32_t circle_path[] = { /*VG circle path*/ + VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1, + VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */ + VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */ + VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */ + VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */ + VLC_OP_END + }; + err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(circle_path), circle_path, + (vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1, + ((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f); + } + else if(dsc->radius > 0) { + float tang = ((float)rad * BEZIER_OPTIM_CIRCLE); + int32_t cpoff = (int32_t)tang; + int32_t rounded_path[] = { /*VG rounded rectangular path*/ + VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1, + VLC_OP_LINE, rel_coords.x2 - rad + 1, rel_coords.y1, /* top */ + VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */ + VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 - rad + 1, /* right */ + VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */ + VLC_OP_LINE, rel_coords.x1 + rad, rel_coords.y2 + 1, /* bottom */ + VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */ + VLC_OP_LINE, rel_coords.x1, rel_coords.y1 + rad, /* left */ + VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */ + VLC_OP_END + }; + err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(rounded_path), rounded_path, + (vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1, + ((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f); + } + else { + int32_t rect_path[] = { /*VG rectangular path*/ + VLC_OP_MOVE, rel_coords.x1, rel_coords.y1, + VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y1, + VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 + 1, + VLC_OP_LINE, rel_coords.x1, rel_coords.y2 + 1, + VLC_OP_LINE, rel_coords.x1, rel_coords.y1, + VLC_OP_END + }; + err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(rect_path), rect_path, + (vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1, + ((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f); + } + + VG_LITE_ERR_RETURN_INV(err, "Init path failed."); + vg_lite_identity(&matrix); + + /*** Init Color/Gradient ***/ + if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) { + uint32_t colors[2]; + uint32_t stops[2]; + lv_color32_t col32[2]; + + /* Gradient setup */ + uint8_t cnt = MAX(dsc->bg_grad.stops_count, 2); + for(uint8_t i = 0; i < cnt; i++) { + col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/ + stops[i] = dsc->bg_grad.stops[i].frac; +#if LV_COLOR_DEPTH==16 + colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.blue << 16) | + ((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.red; +#else /*LV_COLOR_DEPTH==32*/ + /* watchout: red and blue color components are inverted versus vg_lite_color_t order */ + colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.red << 16) | + ((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.blue; +#endif + } + + lv_memset_00(&gradient, sizeof(vg_lite_linear_gradient_t)); + + err = vg_lite_init_grad(&gradient); + VG_LITE_ERR_RETURN_INV(err, "Init gradient failed"); + + err = vg_lite_set_grad(&gradient, cnt, colors, stops); + VG_LITE_ERR_RETURN_INV(err, "Set gradient failed."); + + err = vg_lite_update_grad(&gradient); + VG_LITE_ERR_RETURN_INV(err, "Update gradient failed."); + + grad_matrix = vg_lite_get_grad_matrix(&gradient); + vg_lite_identity(grad_matrix); + vg_lite_translate((float)rel_coords.x1, (float)rel_coords.y1, grad_matrix); + + if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) { + vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix); + vg_lite_rotate(90.0f, grad_matrix); + } + else { /*LV_GRAD_DIR_HOR*/ + vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix); + } + } + + lv_opa_t bg_opa = dsc->bg_opa; + lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/ + if(bg_opa <= (lv_opa_t)LV_OPA_MAX) { + /* Only pre-multiply color if hardware pre-multiplication is not present */ + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { + bg_col32.ch.red = (uint8_t)(((uint16_t)bg_col32.ch.red * bg_opa) >> 8); + bg_col32.ch.green = (uint8_t)(((uint16_t)bg_col32.ch.green * bg_opa) >> 8); + bg_col32.ch.blue = (uint8_t)(((uint16_t)bg_col32.ch.blue * bg_opa) >> 8); + } + bg_col32.ch.alpha = bg_opa; + } + +#if LV_COLOR_DEPTH==16 + vgcol = bg_col32.full; +#else /*LV_COLOR_DEPTH==32*/ + vgcol = ((uint32_t)bg_col32.ch.alpha << 24) | ((uint32_t)bg_col32.ch.blue << 16) | + ((uint32_t)bg_col32.ch.green << 8) | (uint32_t)bg_col32.ch.red; +#endif + + /*Clean & invalidate cache*/ + lv_vglite_invalidate_cache(); + + /*** Draw rectangle ***/ + if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) { + err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); + } + else { + err = vg_lite_draw_gradient(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER); + } + VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed."); + + err = vg_lite_finish(); + VG_LITE_ERR_RETURN_INV(err, "Finish failed."); + + err = vg_lite_clear_path(&path); + VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); + + if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) { + err = vg_lite_clear_grad(&gradient); + VG_LITE_ERR_RETURN_INV(err, "Clear gradient failed."); + } + + return LV_RES_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h new file mode 100644 index 000000000..d708e7b42 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h @@ -0,0 +1,77 @@ +/** + * @file lv_draw_vglite_rect.h + * + */ + +/** + * MIT License + * + * Copyright 2021, 2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_DRAW_VGLITE_RECT_H +#define LV_DRAW_VGLITE_RECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_VG_LITE +#include "lv_gpu_nxp_vglite.h" +#include "../../lv_draw_rect.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Draw rectangle shape with effects (rounded corners, gradient) + * + * @param draw_ctx drawing context + * @param dsc description of the rectangle + * @param coords the area where rectangle is clipped + */ +lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_VGLITE_RECT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.c new file mode 100644 index 000000000..f65ec1d48 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.c @@ -0,0 +1,153 @@ +/** + * @file lv_gpu_nxp_vglite.c + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_gpu_nxp_vglite.h" + +#if LV_USE_GPU_NXP_VG_LITE +#include "../../../core/lv_refr.h" +#if BLIT_DBG_AREAS + #include "lv_draw_vglite_blend.h" +#endif + +/********************* + * DEFINES + *********************/ + +#if LV_COLOR_DEPTH==16 + #define VG_LITE_PX_FMT VG_LITE_RGB565 +#elif LV_COLOR_DEPTH==32 + #define VG_LITE_PX_FMT VG_LITE_BGRA8888 +#else + #error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32. +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source) +{ + /*Test for memory alignment*/ + if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U) + VG_LITE_RETURN_INV("%s buffer (0x%x) not aligned to %d.", source ? "Src" : "Dest", + (size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE); + + /*Test for stride alignment*/ + if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) + VG_LITE_RETURN_INV("Src buffer stride (%d bytes) not aligned to %d bytes.", stride, + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); + + vgbuf->format = VG_LITE_PX_FMT; + vgbuf->tiled = VG_LITE_LINEAR; + vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE; + vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE; + + vgbuf->width = (int32_t)width; + vgbuf->height = (int32_t)height; + vgbuf->stride = (int32_t)stride; + + lv_memset_00(&vgbuf->yuv, sizeof(vgbuf->yuv)); + + vgbuf->memory = (void *)ptr; + vgbuf->address = (uint32_t)vgbuf->memory; + vgbuf->handle = NULL; + + return LV_RES_OK; +} + +#if BLIT_DBG_AREAS +void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + lv_area_t * fill_area, lv_color_t color) +{ + lv_area_t a; + + /* top line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x2; + a.y1 = fill_area->y1; + a.y2 = fill_area->y1; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + + /* bottom line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x2; + a.y1 = fill_area->y2; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + /* left line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x1; + a.y1 = fill_area->y1; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + /* right line */ + a.x1 = fill_area->x2; + a.x2 = fill_area->x2; + a.y1 = fill_area->y1; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); +} +#endif /* BLIT_DBG_AREAS */ + +void lv_vglite_invalidate_cache(void) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + if(disp->driver->clean_dcache_cb) + disp->driver->clean_dcache_cb(disp->driver); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.h new file mode 100644 index 000000000..c22cae185 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.h @@ -0,0 +1,185 @@ +/** + * @file lv_gpu_nxp_vglite.h + * + */ + +/** + * MIT License + * + * Copyright 2020-2022 NXP + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LV_GPU_NXP_VGLITE_H +#define LV_GPU_NXP_VGLITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_VG_LITE +#include "vg_lite.h" +#include "../../sw/lv_draw_sw.h" +#include "../../../misc/lv_log.h" +#include "fsl_debug_console.h" + +/********************* + * DEFINES + *********************/ + +/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */ +#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1) + +/** Stride in px required by VG-Lite HW. Don't change this. */ +#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U + +#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS +/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/ +#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES +/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/ +#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0 +#endif + +/* Draw rectangles around BLIT tiles */ +#define BLIT_DBG_AREAS 0 + +/* Print detailed info to SDK console (NOT to LVGL log system) */ +#define BLIT_DBG_VERBOSE 0 + +/* Verbose debug print */ +#if BLIT_DBG_VERBOSE +#define PRINT_BLT PRINTF +#else +#define PRINT_BLT(...) +#endif + +/* The optimal Bezier control point offset for radial unit + * see: https://spencermortensen.com/articles/bezier-circle/ + **/ +#define BEZIER_OPTIM_CIRCLE 0.551915024494f + +/* Draw lines for control points of Bezier curves */ +#define BEZIER_DBG_CONTROL_POINTS 0 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Fills vg_lite_buffer_t structure according given parameters. + * + * @param[in/out] vgbuf Buffer structure to be filled + * @param[in] width Width of buffer in pixels + * @param[in] height Height of buffer in pixels + * @param[in] stride Stride of the buffer in bytes + * @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements) + * @param[in] source Boolean to check if this is a source buffer + */ +lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source); + +#if BLIT_DBG_AREAS +/** + * Draw a simple rectangle, 1 px line width. + * + * @param dest_buf Destination buffer + * @param dest_width Destination buffer width (must be aligned on 16px) + * @param dest_height Destination buffer height + * @param fill_area Rectangle coordinates + * @param color Rectangle color + */ +void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + lv_area_t * fill_area, lv_color_t color); +#endif + +/** + * Clean & invalidate cache. + */ +void lv_vglite_invalidate_cache(void); + +/********************** + * MACROS + **********************/ + +#define VG_LITE_COND_STOP(cond, txt) \ + do { \ + if (cond) { \ + LV_LOG_ERROR("%s. STOP!", txt); \ + for ( ; ; ); \ + } \ + } while(0) + +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS +#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \ + do { \ + if(err != VG_LITE_SUCCESS) { \ + LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + return LV_RES_INV; \ + } \ + } while (0) +#else +#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \ + do { \ + if(err != VG_LITE_SUCCESS) { \ + return LV_RES_INV; \ + } \ + }while(0) +#endif /*LV_GPU_NXP_VG_LITE_LOG_ERRORS*/ + +#if LV_GPU_NXP_VG_LITE_LOG_TRACES +#define VG_LITE_LOG_TRACE(fmt, ...) \ + do { \ + LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + } while (0) + +#define VG_LITE_RETURN_INV(fmt, ...) \ + do { \ + LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + return LV_RES_INV; \ + } while (0) +#else +#define VG_LITE_LOG_TRACE(fmt, ...) \ + do { \ + } while (0) +#define VG_LITE_RETURN_INV(fmt, ...) \ + do { \ + return LV_RES_INV; \ + }while(0) +#endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/ + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_NXP_VGLITE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c deleted file mode 100644 index a6fb49b7b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c +++ /dev/null @@ -1,446 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp.c - * - */ - -/** - * MIT License - * - * Copyright (c) 2020 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_gpu_nxp_pxp.h" - -#if LV_USE_GPU_NXP_PXP - -#include "../misc/lv_mem.h" -#include "../misc/lv_log.h" - -#include "fsl_pxp.h" -#include "fsl_cache.h" - -/********************* - * DEFINES - *********************/ - -#if LV_COLOR_16_SWAP - #error Color swap not implemented. Disable LV_COLOR_16_SWAP feature. -#endif - -#if LV_COLOR_DEPTH==16 - #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565 - #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565 - #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565 -#else - #error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16. -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void lv_gpu_nxp_pxp_run(void); -static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, - lv_coord_t src_width, - lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa); - -/********************** - * STATIC VARIABLES - **********************/ - -static bool colorKeyEnabled = false; -static uint32_t colorKey = 0x0; - -static bool recolorEnabled = false; -static lv_color_t recolor = {.full = 0x0}; -static lv_opa_t recolorOpa = 0x0; - -static lv_nxp_pxp_cfg_t pxp_cfg; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Reset and initialize PXP device. This function should be called as a part - * of display init sequence. - * - * @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information. - */ -lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg) -{ - if(!cfg || !cfg->pxp_interrupt_deinit || !cfg->pxp_interrupt_init || !cfg->pxp_run) { - LV_LOG_ERROR("PXP configuration error. Check callback pointers."); - return LV_RES_INV; - } - - PXP_Init(PXP); - PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/ - PXP_EnableInterrupts(PXP, kPXP_CompleteInterruptEnable); - - pxp_cfg = *cfg; - if(pxp_cfg.pxp_interrupt_init() != LV_RES_OK) { - PXP_Deinit(PXP); - LV_LOG_ERROR("PXP interrupt init error. Check pxp_interrupt_init callback."); - return LV_RES_INV; - } - - colorKey = lv_color_to32(LV_COLOR_CHROMA_KEY); - - return LV_RES_OK; -} - -/** - * Disable PXP device. Should be called during display deinit sequence. - */ -void lv_gpu_nxp_pxp_deinit(void) -{ - pxp_cfg.pxp_interrupt_deinit(); - PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable); - PXP_Deinit(LV_GPU_NXP_PXP_ID); -} - -/** - * Fill area, with optional opacity. - * - * @param[in/out] dest_buf destination buffer - * @param[in] dest_width width (stride) of destination buffer in pixels - * @param[in] fill_area area to fill - * @param[in] color color - * @param[in] opa transparency of the color - */ -void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color, - lv_opa_t opa) -{ - PXP_Init(LV_GPU_NXP_PXP_ID); - PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ - PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ - - /*OUT buffer configure*/ - pxp_output_buffer_config_t outputConfig = { - .pixelFormat = PXP_OUT_PIXEL_FORMAT, - .interlacedMode = kPXP_OutputProgressive, - .buffer0Addr = (uint32_t)(dest_buf + dest_width * fill_area->y1 + fill_area->x1), - .buffer1Addr = (uint32_t)NULL, - .pitchBytes = dest_width * sizeof(lv_color_t), - .width = fill_area->x2 - fill_area->x1 + 1, - .height = fill_area->y2 - fill_area->y1 + 1, - }; - - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig); - - if(opa > LV_OPA_MAX) { - /*Simple color fill without opacity - AS disabled, PS as color generator*/ - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable AS.*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable PS.*/ - PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color)); - } - else { - /*Fill with opacity - AS used as source (same as OUT), PS used as color generator, blended together*/ - pxp_as_buffer_config_t asBufferConfig; - pxp_porter_duff_config_t pdConfig; - - /*Set AS to OUT*/ - asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT; - asBufferConfig.bufferAddr = (uint32_t)outputConfig.buffer0Addr; - asBufferConfig.pitchBytes = outputConfig.pitchBytes; - - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, fill_area->x2 - fill_area->x1 + 1, - fill_area->y2 - fill_area->y1 + 1); - - /*Disable PS, use as color generator*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color)); - - /*Configure Porter-Duff blending - For RGB 565 only!*/ - pdConfig.enable = 1; - pdConfig.dstColorMode = kPXP_PorterDuffColorStraight; - pdConfig.srcColorMode = kPXP_PorterDuffColorStraight; - pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha; - pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha; - pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight; - pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight; - pdConfig.srcGlobalAlpha = opa; - pdConfig.dstGlobalAlpha = 255 - opa; - pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/ - pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/ - PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); - } - - lv_gpu_nxp_pxp_run(); /*Start PXP task*/ -} - -/** - * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects. - * - * By default, image is copied directly, with optional opacity configured by \p opa. - * Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function. - * Recoloring can be enabled by calling lv_gpu_nxp_pxp_enable_recolor() before calling this function. - * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered. - * - * @param[in/out] dest destination buffer - * @param[in] dest_width width (stride) of destination buffer in pixels - * @param[in] src source buffer - * @param[in] src_with width (stride) of source buffer in pixels - * @param[in] copy_w width of area to be copied from src to dest - * @param[in] copy_h height of area to be copied from src to dest - * @param[in] opa opacity of the result - */ -void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width, - lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa) -{ - - if(recolorEnabled) { /*switch to recolor version of blit*/ - lv_gpu_nxp_pxp_blit_recolor(dest, dest_width, src, src_width, copy_width, copy_height, opa, recolor, recolorOpa); - return; - }; - - PXP_Init(PXP); - PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/ - PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/ - - pxp_output_buffer_config_t outputBufferConfig; - pxp_as_buffer_config_t asBufferConfig; - pxp_as_blend_config_t asBlendConfig; - - asBlendConfig.alpha = opa; - asBlendConfig.invertAlpha = false; - asBlendConfig.alphaMode = kPXP_AlphaRop; - asBlendConfig.ropMode = kPXP_RopMergeAs; - - if(opa >= LV_OPA_MAX && !colorKeyEnabled) { - /*Simple blit, no effect - Disable PS buffer*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - } - else { - /*Alpha blending or color keying enabled - PS must be enabled to fetch background pixels - PS and OUT buffers are the same, blend will be done in-place*/ - pxp_ps_buffer_config_t psBufferConfig = { - .pixelFormat = PXP_PS_PIXEL_FORMAT, - .swapByte = false, - .bufferAddr = (uint32_t)dest, - .bufferAddrU = 0U, - .bufferAddrV = 0U, - .pitchBytes = dest_width * sizeof(lv_color_t) - }; - asBlendConfig.alphaMode = kPXP_AlphaOverride; - PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig); - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1, copy_height - 1); - } - - /*AS buffer - source image*/ - asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT; - asBufferConfig.bufferAddr = (uint32_t)src; - asBufferConfig.pitchBytes = src_width * sizeof(lv_color_t); - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); - PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); - - if(colorKeyEnabled) { - PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKey, colorKey); - } - PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKeyEnabled); - - /*Output buffer.*/ - outputBufferConfig.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT; - outputBufferConfig.interlacedMode = kPXP_OutputProgressive; - outputBufferConfig.buffer0Addr = (uint32_t)dest; - outputBufferConfig.buffer1Addr = (uint32_t)0U; - outputBufferConfig.pitchBytes = dest_width * sizeof(lv_color_t); - outputBufferConfig.width = copy_width; - outputBufferConfig.height = copy_height; - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - - lv_gpu_nxp_pxp_run(); /* Start PXP task */ -} - -/** - * @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() - * - * Color key is defined by symbol in lv_conf.h - */ -void lv_gpu_nxp_pxp_enable_color_key(void) -{ - colorKeyEnabled = true; -} - -/** - * @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() - * - */ -void lv_gpu_nxp_pxp_disable_color_key(void) -{ - colorKeyEnabled = false; -} - -/** - * @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() - * - * @param[in] color recolor value - * @param[in] opa effect opacity - */ -void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa) -{ - recolorEnabled = true; - recolor = color; - recolorOpa = opa; - -} - -/** - * @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() - */ -void lv_gpu_nxp_pxp_disable_recolor(void) -{ - recolorEnabled = false; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * @brief Start PXP job and wait for results - * - * Function used internally to start PXP task according current device - * configuration. - */ -static void lv_gpu_nxp_pxp_run(void) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - if(disp && disp->driver->clean_dcache_cb) { /* Clean & invalidate cache */ - disp->driver->clean_dcache_cb(disp->driver); - } - - pxp_cfg.pxp_run(); -} - -/** - * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with recoloring. - * - * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered. - * - * @param[in/out] dest destination buffer - * @param[in] dest_width width (stride) of destination buffer in pixels - * @param[in] src source buffer - * @param[in] src_with width (stride) of source buffer in pixels - * @param[in] copy_w width of area to be copied from src to dest - * @param[in] copy_h height of area to be copied from src to dest - * @param[in] opa opacity of the result - * @param[in] recolor recolor value - * @param[in] recolorOpa effect opacity - */ -static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, - lv_coord_t src_width, - lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa) -{ - pxp_output_buffer_config_t outputBufferConfig; - pxp_as_buffer_config_t asBufferConfig; - - if(colorKeyEnabled) { - /*should never get here, recolor & color keying not supported. Draw black box instead.*/ - const lv_area_t fill_area = {.x1 = 0, .y1 = 0, .x2 = copy_width - 1, .y2 = copy_height - 1}; - lv_gpu_nxp_pxp_fill(dest, dest_width, &fill_area, lv_color_black(), LV_OPA_MAX); - LV_LOG_WARN("Recoloring and color keying is not supported. Black rectangle rendered."); - return ; - } - else { - /*Recoloring without color keying*/ - if(opa > LV_OPA_MAX) { - /*Recolor with full opacity - AS source image, PS color generator, OUT destination*/ - PXP_Init(PXP); - PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/ - PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/ - - /*AS buffer - source image*/ - asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT; - asBufferConfig.bufferAddr = (uint32_t)src; - asBufferConfig.pitchBytes = src_width * sizeof(lv_color_t); - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); - - /*Disable PS buffer, use as color generator*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(recolor)); - - /*Output buffer*/ - outputBufferConfig.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT; - outputBufferConfig.interlacedMode = kPXP_OutputProgressive; - outputBufferConfig.buffer0Addr = (uint32_t)dest; - outputBufferConfig.buffer1Addr = (uint32_t)0U; - outputBufferConfig.pitchBytes = dest_width * sizeof(lv_color_t); - outputBufferConfig.width = copy_width; - outputBufferConfig.height = copy_height; - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - - pxp_porter_duff_config_t pdConfig; - - /*Configure Porter-Duff blending - For RGB 565 only!*/ - pdConfig.enable = 1; - pdConfig.dstColorMode = kPXP_PorterDuffColorStraight; - pdConfig.srcColorMode = kPXP_PorterDuffColorStraight; - pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha; - pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha; - pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight; - pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight; - pdConfig.srcGlobalAlpha = recolorOpa; - pdConfig.dstGlobalAlpha = 255 - recolorOpa; - pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/ - pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/ - PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); - - lv_gpu_nxp_pxp_run(); /*Start PXP task*/ - - } - else { - /*Recolor with transparency*/ - - /*Step 1: Recolor with full opacity to temporary buffer*/ - lv_color_t * tmpBuf = (lv_color_t *)lv_mem_buf_get(copy_width * copy_height * sizeof(lv_color_t)); - lv_gpu_nxp_pxp_blit_recolor(tmpBuf, copy_width, src, src_width, copy_width, copy_height, LV_OPA_COVER, recolor, - recolorOpa); - - /*Step 2: BLIT temporary results with required opacity to output*/ - lv_gpu_nxp_pxp_disable_recolor(); /*make sure to take BLIT path, not the recolor*/ - lv_gpu_nxp_pxp_blit(dest, dest_width, tmpBuf, copy_width, copy_width, copy_height, opa); - lv_gpu_nxp_pxp_enable_recolor(recolor, recolorOpa); /*restore state*/ - - /*Step 3: Clean-up memory*/ - lv_mem_buf_release(tmpBuf); - } - } -} - -#endif /* LV_USE_GPU_NXP_PXP */ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h deleted file mode 100644 index 8d812882c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp.h - * - */ - -/** - * MIT License - * - * Copyright (c) 2020 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_ -#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_PXP - -#include "../misc/lv_area.h" -#include "../misc/lv_color.h" - -/********************* - * DEFINES - *********************/ - -/** PXP module instance to use*/ -#define LV_GPU_NXP_PXP_ID PXP - -/** PXP interrupt line I*/ -#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn - -#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT -/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/ -#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 32 -#endif - -#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT -/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/ -#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 16 -#endif - -#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT -/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */ -#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 32 -#endif - -#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT -/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/ -#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 64 -#endif - -#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT -/** Minimum area (in pixels) to be filled by PXP with transparency*/ -#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 32 -#endif - -/********************** - * TYPEDEFS - **********************/ -/** - * NXP PXP device configuration - call-backs used for - * interrupt init/wait/deinit. - */ -typedef struct { - /** Callback for PXP interrupt initialization*/ - lv_res_t (*pxp_interrupt_init)(void); - - /** Callback for PXP interrupt de-initialization*/ - void (*pxp_interrupt_deinit)(void); - - /** Callback that should start PXP and wait for operation complete*/ - void (*pxp_run)(void); -} lv_nxp_pxp_cfg_t; - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Reset and initialize PXP device. This function should be called as a part - * of display init sequence. - * - * @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information. - */ -lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg); - -/** - * Disable PXP device. Should be called during display deinit sequence. - */ -void lv_gpu_nxp_pxp_deinit(void); - -/** - * Fill area, with optional opacity. - * - * @param[in/out] dest_buf destination buffer - * @param[in] dest_width width (stride) of destination buffer in pixels - * @param[in] fill_area area to fill - * @param[in] color color - * @param[in] opa transparency of the color - */ -void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color, - lv_opa_t opa); - -/** - * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects. - * - * By default, image is copied directly, with optional opacity configured by \p opa. - * Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function. - * Recoloring can be enabled by calling lv_gpu_nxp_pxp_enable_recolor() before calling this function. - * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered. - * - * @param[in/out] dest destination buffer - * @param[in] dest_width width (stride) of destination buffer in pixels - * @param[in] src source buffer - * @param[in] src_with width (stride) of source buffer in pixels - * @param[in] copy_w width of area to be copied from src to dest - * @param[in] copy_h height of area to be copied from src to dest - * @param[in] opa opacity of the result - */ -void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width, - lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa); - -/** - * @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() - * - * Color key is defined by LV_COLOR_TRANSP symbol in lv_conf.h - */ -void lv_gpu_nxp_pxp_enable_color_key(void); - -/** - * @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() - * - */ -void lv_gpu_nxp_pxp_disable_color_key(void); - -/** - * @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() - * - * @param[in] color recolor value - * @param[in] opa effect opacity - */ -void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa); - -/** - * @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() - */ -void lv_gpu_nxp_pxp_disable_recolor(void); - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_GPU_NXP_PXP*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c deleted file mode 100644 index 43dd88179..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c +++ /dev/null @@ -1,770 +0,0 @@ -/** - * @file lv_gpu_nxp_vglite.c - * - */ - -/** - * MIT License - * - * Copyright (c) 2020 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_gpu_nxp_vglite.h" - -#if LV_USE_GPU_NXP_VG_LITE - -#include "lvgl.h" -#include "../misc/lv_log.h" -#include "fsl_cache.h" -#include "vg_lite.h" -#include "fsl_debug_console.h" - -/********************* - * DEFINES - *********************/ - -#if LV_COLOR_DEPTH==16 - #define VGLITE_PX_FMT VG_LITE_RGB565 -#else - #error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16. -#endif - -/* Enable BLIT quality degradation workaround for RT595 */ -#define RT595_BLIT_WRKRND_ENABLED 1 - -/* If LV_HOR_RES_MAX/LV_VER_RES_MAX is higher than this value, workaround will be enabled */ -#define RT595_BLIT_WRKRND_THR 352 - -/* Print detailed info to SDK console (NOT to LVGL log system) */ -#define BLIT_DBG_VERBOSE 0 - -/* Draw rectangles around BLIT tiles */ -#define BLIT_DBG_AREAS 0 - -/* Redirect PRINT to SDK PRINTF */ -#define PRINT PRINTF - -/* Verbose debug print */ -#if BLIT_DBG_VERBOSE - #define PRINT_BLT PRINTF -#else - #define PRINT_BLT(...) -#endif - -/* Internal compound symbol */ -#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ - defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ - ((LV_HOR_RES_MAX > RT595_BLIT_WRKRND_THR) || (LV_VER_RES_MAX > RT595_BLIT_WRKRND_THR)) && \ - RT595_BLIT_WRKRND_ENABLED -#define _BLIT_SPLIT_ENABLED 1 -#else -#define _BLIT_SPLIT_ENABLED 0 -#endif - -/* BLIT split threshold - BLITs with width or height higher than this value will be done - * in multiple steps. Value must be 16-aligned. Don't change. - * */ -#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352 - - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr, bool source); - -static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit); -#if _BLIT_SPLIT_ENABLED -static void _align_x(lv_area_t * area, lv_color_t ** buf); -static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx); -static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit); -#if BLIT_DBG_AREAS -static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, - lv_area_t * fill_area, lv_color_t color); -#endif -static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit); -#endif - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -#define CHECK(cond, txt) \ - do { \ - if (cond) { \ - PRINT("%s. STOP!\n", txt); \ - for ( ; ; ); \ - } \ - } while(0) - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/*** - * Fills rectangular area in buffer. - * @param[in] dest_buf Destination buffer pointer (must be aligned on 32 bytes) - * @param[in] dest_width Destination buffer width in pixels (must be aligned on 16 px) - * @param[in] dest_height Destination buffer height in pixels - * @param[in] fill_area Area to be filled - * @param[in] color Fill color - * @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill) - * @retval LV_RES_OK Fill completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, - const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa) -{ - vg_lite_buffer_t rt; - vg_lite_rectangle_t rect; - vg_lite_error_t err = VG_LITE_SUCCESS; - lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - if(_init_vg_buf(&rt, (uint32_t) dest_width, (uint32_t) dest_height, (uint32_t) dest_width * sizeof(lv_color_t), - (const lv_color_t *) dest_buf, false) != LV_RES_OK) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("init_vg_buf reported error. Fill failed."); -#endif - return LV_RES_INV; - } - - if(opa >= (lv_opa_t) LV_OPA_MAX) { /*Opaque fill*/ - rect.x = fill_area->x1; - rect.y = fill_area->y1; - rect.width = (int32_t) fill_area->x2 - (int32_t) fill_area->x1 + 1; - rect.height = (int32_t) fill_area->y2 - (int32_t) fill_area->y1 + 1; - - if(disp != NULL && disp->driver->clean_dcache_cb != NULL) { /*Clean & invalidate cache*/ - disp->driver->clean_dcache_cb(disp->driver); - } - - err = vg_lite_clear(&rt, &rect, col32.full); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_clear reported error. Fill failed."); -#endif - return LV_RES_INV; - } - err = vg_lite_finish(); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_finish reported error. Fill failed."); -#endif - return LV_RES_INV; - } - } - else { /*fill with transparency*/ - - vg_lite_path_t path; - lv_color32_t colMix; - int16_t path_data[] = { /*VG rectangular path*/ - VLC_OP_MOVE, fill_area->x1, fill_area->y1, - VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1, - VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1, - VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1, - VLC_OP_LINE, fill_area->x1, fill_area->y1, - VLC_OP_END - }; - - err = vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data, - (vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, ((vg_lite_float_t) fill_area->x2) + 1.0f, - ((vg_lite_float_t) fill_area->y2) + 1.0f); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_init_path() failed."); -#endif - return LV_RES_INV; - } - - colMix.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); /*Pre-multiply color*/ - colMix.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8); - colMix.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8); - colMix.ch.alpha = opa; - - if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ - disp->driver->clean_dcache_cb(disp->driver); - } - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - - /*Draw rectangle*/ - err = vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_draw() failed."); -#endif - vg_lite_clear_path(&path); - return LV_RES_INV; - } - - err = vg_lite_finish(); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_finish() failed."); -#endif - return LV_RES_INV; - } - - err = vg_lite_clear_path(&path); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_clear_path() failed."); -#endif - return LV_RES_INV; - } - } - - if(err == VG_LITE_SUCCESS) { - return LV_RES_OK; - } - else { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("VG Lite Fill failed."); -#endif - return LV_RES_INV; - } -} - -/*** - * BLock Image Transfer. - * @param[in] blit Description of the transfer - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) -{ -#if _BLIT_SPLIT_ENABLED - - lv_res_t rv = LV_RES_INV; - - if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) { - PRINT_BLT("Blit check failed\n"); - return LV_RES_INV; - } - - PRINT_BLT("BLIT from: " - "Area: %03d,%03d - %03d,%03d " - "Addr: %d\n\n", - blit->src_area.x1, blit->src_area.y1, - blit->src_area.x2, blit->src_area.y2, - (uintptr_t) blit->src); - - PRINT_BLT("BLIT to: " - "Area: %03d,%03d - %03d,%03d " - "Addr: %d\n\n", - blit->dst_area.x1, blit->dst_area.y1, - blit->dst_area.x2, blit->dst_area.y2, - (uintptr_t) blit->src); - - /* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */ - _align_x(&blit->src_area, (lv_color_t **)&blit->src); - _align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t)); - _align_x(&blit->dst_area, (lv_color_t **)&blit->dst); - _align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t)); - - /* Stage 2: If we're in limit, do a single BLIT */ - if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) && - (blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) { - PRINT_BLT("Simple blit!\n"); - return _lv_gpu_nxp_vglite_blit_single(blit); - }; - - /* Stage 3: Split the BLIT into multiple tiles */ - PRINT_BLT("Split blit!\n"); - - PRINT_BLT("Blit " - "([%03d,%03d], [%03d,%03d]) -> " - "([%03d,%03d], [%03d,%03d]) | " - "([%03dx%03d] -> [%03dx%03d]) | " - "A:(%d -> %d)\n", - blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2, - blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2, - lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area), - lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area), - (uintptr_t) blit->src, (uintptr_t) blit->dst); - - - uint32_t totalWidth = lv_area_get_width(&blit->src_area); - uint32_t totalHeight = lv_area_get_height(&blit->src_area); - - lv_gpu_nxp_vglite_blit_info_t tileBlit; - - /* Number of tiles needed */ - int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / - LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / - LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - - /* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as - * the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be - * different */ - int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0; - int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0; - - PRINT_BLT("\n"); - PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX); - - tileBlit = *blit; - - for(int tileY = 0; tileY < totalTilesY; tileY++) { - - tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */ - tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */ - } - tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof( - lv_color_t); /* stride in px! */ - - tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */ - tileBlit.dst_area.y2 = tileBlit.src_area.y2; - - tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof( - lv_color_t); /* stride in px! */ - - for(int tileX = 0; tileX < totalTilesX; tileX++) { - - if(tileX == 0) { - /* 1st tile is special - there may be a gap between buffer start pointer - * and area.x1 value, as the pointer has to be aligned. - * tileBlit.src pointer - keep init value from Y-loop. - * Also, 1st tile start is not shifted! shift is applied from 2nd tile */ - tileBlit.src_area.x1 = blit->src_area.x1; - tileBlit.dst_area.x1 = blit->dst_area.x1; - } - else { - /* subsequent tiles always starts from 0, but shifted*/ - tileBlit.src_area.x1 = 0 + shiftSrcX; - tileBlit.dst_area.x1 = 0 + shiftDstX; - /* and advance start pointer + 1 tile size */ - tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - } - - /* Clip tile end coordinates */ - tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - } - - tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - } - - if(tileX < (totalTilesX - 1)) { - /* And adjust end coords if shifted, but not for last tile! */ - tileBlit.src_area.x2 += shiftSrcX; - tileBlit.dst_area.x2 += shiftDstX; - } - - rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit); - -#if BLIT_DBG_AREAS - _draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area, LV_COLOR_RED); - _draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area, - LV_COLOR_GREEN); -#endif - - PRINT_BLT("Tile [%d, %d]: " - "([%d,%d], [%d,%d]) -> " - "([%d,%d], [%d,%d]) | " - "([%dx%d] -> [%dx%d]) | " - "A:(0x%8X -> 0x%8X) %s\n", - tileX, tileY, - tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2, - tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2, - lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area), - lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area), - (uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst, - rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!"); - - if(rv != LV_RES_OK) { /* if anything goes wrong... */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("Split BLIT failed. Trying SW BLIT instead."); -#endif - _sw_blit(&tileBlit); - rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */ - } - - } - PRINT_BLT(" \n"); - } - - return rv; /* should never fail */ - -#else /* non RT595 */ - /* Just pass down */ - return _lv_gpu_nxp_vglite_blit_single(blit); -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/*** - * BLock Image Transfer - single direct BLIT. - * @param[in] blit Description of the transfer - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit) -{ - vg_lite_buffer_t src_vgbuf, dst_vgbuf; - vg_lite_error_t err = VG_LITE_SUCCESS; - uint32_t rect[4]; - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - if(blit == NULL) { - /*Wrong parameter*/ - return LV_RES_INV; - } - - if(blit->opa < (lv_opa_t) LV_OPA_MIN) { - return LV_RES_OK; /*Nothing to BLIT*/ - } - - /*Wrap src/dst buffer into VG-Lite buffer*/ - if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride, - blit->src, true) != LV_RES_OK) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); -#endif - return LV_RES_INV; - } - - if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride, - blit->dst, false) != LV_RES_OK) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); -#endif - return LV_RES_INV; - } - - rect[0] = (uint32_t) blit->src_area.x1; /* start x */ - rect[1] = (uint32_t) blit->src_area.y1; /* start y */ - rect[2] = (uint32_t) blit->src_area.x2 - (uint32_t) blit->src_area.x1 + 1U; /* width */ - rect[3] = (uint32_t) blit->src_area.y2 - (uint32_t) blit->src_area.y1 + 1U; /* height */ - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix); - - if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ - disp->driver->clean_dcache_cb(disp->driver); - } - - uint32_t color; - vg_lite_blend_t blend; - if(blit->opa >= (uint8_t) LV_OPA_MAX) { - color = 0x0; - blend = VG_LITE_BLEND_NONE; - } - else { - uint32_t opa = (uint32_t) blit->opa; - color = (opa << 24) | (opa << 16) | (opa << 8) | opa; - blend = VG_LITE_BLEND_SRC_OVER; - src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; - } - - err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_blit_rect() failed."); -#endif - return LV_RES_INV; - } - - err = vg_lite_finish(); - if(err != VG_LITE_SUCCESS) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_finish() failed."); -#endif - return LV_RES_INV; - } - - if(err == VG_LITE_SUCCESS) { - return LV_RES_OK; - } - else { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("vg_lite_blit_rect or vg_lite_finish reported error. BLIT failed."); -#endif - return LV_RES_INV; - } -} - -/*** - * Fills vg_lite_buffer_t structure according given parameters. - * @param[out] dst Buffer structure to be filled - * @param[in] width Width of buffer in pixels - * @param[in] height Height of buffer in pixels - * @param[in] stride Stride of the buffer in bytes - * @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements) - */ -static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr, bool source) -{ - if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0U) { /*Test for alignment*/ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("ptr (0x%X) not aligned to %d.", (size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE); -#endif - return LV_RES_INV; - } - - if(source && - (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride, - LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); -#endif - return LV_RES_INV; - } - - dst->format = VGLITE_PX_FMT; - dst->tiled = VG_LITE_LINEAR; - dst->image_mode = VG_LITE_NORMAL_IMAGE_MODE; - dst->transparency_mode = VG_LITE_IMAGE_OPAQUE; - - dst->width = (int32_t) width; - dst->height = (int32_t) height; - dst->stride = (int32_t) stride; - - void * r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv)); - if(r_ptr == NULL) { - return LV_RES_INV; - } - - dst->memory = (void *)ptr; - dst->address = (uint32_t) dst->memory; - dst->handle = NULL; - - return LV_RES_OK; -} - -#if _BLIT_SPLIT_ENABLED - -/** - * Software BLIT as a fall-back scenario - * @param[in] blit BLIT configuration - */ -static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit) -{ - int x, y; - - lv_coord_t w = lv_area_get_width(&blit->src_area); - lv_coord_t h = lv_area_get_height(&blit->src_area); - - uint32_t srcStridePx = blit->src_stride / sizeof(lv_color_t); - uint32_t dstStridePx = blit->dst_stride / sizeof(lv_color_t); - - lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1; - lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1; - - if(blit->opa >= LV_OPA_MAX) { - /* simple copy */ - for(y = 0; y < h; y++) { - _lv_memcpy(dst, src, w * sizeof(lv_color_t)); - src += srcStridePx; - dst += dstStridePx; - } - } - else if(blit->opa >= LV_OPA_MIN) { - /* alpha blending */ - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - dst[x] = lv_color_mix(src[x], dst[x], blit->opa); - } - src += srcStridePx; - dst += dstStridePx; - } - } -} - -/** - * Verify BLIT structure - widths, stride, pointer alignment - * @param[in] blit - * @return - */ -static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit) -{ - - if(lv_area_get_width(&blit->src_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("source area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area), - LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); -#endif - return LV_RES_INV; - } - - if(lv_area_get_width(&blit->dst_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("destination area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area), - LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); -#endif - return LV_RES_INV; - } - - if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /* Test for pointer alignment */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("source buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE); -#endif - return LV_RES_INV; - } - /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ - - if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != - 0x0) { /* Test for stride alignment */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride, - LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); -#endif - return LV_RES_INV; - } - - if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != - 0x0) { /* Test for stride alignment */ -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride, - LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); -#endif - return LV_RES_INV; - } - - if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) || - (lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area))) { -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("source and destination buffer areas are not equal."); -#endif - return LV_RES_INV; - } - - return LV_RES_OK; -} - -/*** - * Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only. - * @param[in,out] area Area to be updated - * @param[in,out] buf Pointer to be updated - */ -static void _align_x(lv_area_t * area, lv_color_t ** buf) -{ - - int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH)); - CHECK(alignedAreaStartPx < 0, "Should never happen."); - - area->x1 -= alignedAreaStartPx; - area->x2 -= alignedAreaStartPx; - *buf += alignedAreaStartPx; -} - -/*** - * Move buffer pointer to the area start and update variables, Y-axis only. - * @param[in,out] area Area to be updated - * @param[in,out] buf Pointer to be updated - * @param[in] stridePx Buffer stride in pixels - */ -static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx) -{ - int LineToAlignMem; - int alignedAreaStartPy; - /* find how many lines of pixels will respect memory alignment requirement */ - if(stridePx % LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0) { - alignedAreaStartPy = area->y1; - } - else { - LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); - CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0, - "Complex case: need gcd function."); - alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); - CHECK(alignedAreaStartPy < 0, "Should never happen."); - } - - area->y1 -= alignedAreaStartPy; - area->y2 -= alignedAreaStartPy; - *buf += alignedAreaStartPy * stridePx; -} - -#if BLIT_DBG_AREAS -/*** - * Draws a simple rectangle, 1 px line width. - * @param dest_buf Destination buffer - * @param dest_width Destination buffer width (must be aligned on 16px) - * @param dest_height Destination buffer height - * @param fill_area Rectangle coordinates - * @param color Rectangle color - */ -static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, - lv_area_t * fill_area, lv_color_t color) -{ - - lv_area_t a; - - /* top line */ - a.x1 = fill_area->x1; - a.x2 = fill_area->x2; - a.y1 = fill_area->y1; - a.y2 = fill_area->y1; - lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); - - - /* bottom line */ - a.x1 = fill_area->x1; - a.x2 = fill_area->x2; - a.y1 = fill_area->y2; - a.y2 = fill_area->y2; - lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); - - /* left line */ - a.x1 = fill_area->x1; - a.x2 = fill_area->x1; - a.y1 = fill_area->y1; - a.y2 = fill_area->y2; - lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); - - /* right line */ - a.x1 = fill_area->x2; - a.x2 = fill_area->x2; - a.y1 = fill_area->y1; - a.y2 = fill_area->y2; - lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); -} -#endif /* BLIT_DBG_AREAS */ - -#endif /* _BLIT_SPLIT_ENABLED */ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c index 430f3a23c..e3cdf577a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c @@ -15,6 +15,7 @@ #include "lv_draw_sdl.h" #include "lv_draw_sdl_utils.h" #include "lv_draw_sdl_texture_cache.h" +#include "lv_draw_sdl_layer.h" /********************* * DEFINES @@ -69,6 +70,10 @@ void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx) draw_ctx->draw_arc = lv_draw_sdl_draw_arc; draw_ctx->draw_polygon = lv_draw_sdl_polygon; draw_ctx->draw_bg = lv_draw_sdl_draw_bg; + draw_ctx->layer_init = lv_draw_sdl_layer_init; + draw_ctx->layer_blend = lv_draw_sdl_layer_blend; + draw_ctx->layer_destroy = lv_draw_sdl_layer_destroy; + draw_ctx->layer_instance_size = sizeof(lv_draw_sdl_layer_ctx_t); lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx; draw_ctx_sdl->renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer; draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t)); diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk index 6609c38bc..c5c28b66b 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk @@ -11,6 +11,7 @@ CSRCS += lv_draw_sdl_rect.c CSRCS += lv_draw_sdl_stack_blur.c CSRCS += lv_draw_sdl_texture_cache.c CSRCS += lv_draw_sdl_utils.c +CSRCS += lv_draw_sdl_layer.c DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c index 1ee843f7a..e6007d1a5 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c @@ -13,7 +13,6 @@ #include "../../misc/lv_gc.h" #include "../../core/lv_refr.h" #include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_mask.h" #include "lv_draw_sdl_utils.h" #include "lv_draw_sdl_priv.h" #include "lv_draw_sdl_texture_cache.h" @@ -84,15 +83,16 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL; if(draw_mask || draw_blend) { lv_draw_sdl_context_internals_t * internals = ctx->internals; - LV_ASSERT(internals->mask == NULL && internals->composition == NULL); + LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL); lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area); internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h); - /* Don't need to worry about overflow */ + /* Don't need to worry about integral overflow */ lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1; /* Offset draw area to start with (0,0) of coords */ lv_area_move(coords_out, ofs_x, ofs_y); lv_area_move(clip_out, ofs_x, ofs_y); + internals->target_backup = SDL_GetRenderTarget(ctx->renderer); SDL_SetRenderTarget(ctx->renderer, internals->composition); SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0); SDL_RenderClear(ctx->renderer); @@ -140,7 +140,7 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_ SDL_Rect dst_rect; lv_area_to_sdl_rect(apply_area, &dst_rect); - SDL_SetRenderTarget(ctx->renderer, ctx->base_draw.buf); + SDL_SetRenderTarget(ctx->renderer, internals->target_backup); switch(blend_mode) { case LV_BLEND_MODE_NORMAL: SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND); @@ -173,7 +173,7 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_ SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect); } - internals->mask = internals->composition = NULL; + internals->mask = internals->composition = internals->target_backup = NULL; } SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id, @@ -186,7 +186,10 @@ SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_d if(!result || tex_size->x < w || tex_size->y < h) { lv_coord_t size = next_pow_of_2(LV_MAX(w, h)); int access = SDL_TEXTUREACCESS_STREAMING; - if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) { + if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) { + access = SDL_TEXTUREACCESS_TARGET; + } + else if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) { access = SDL_TEXTUREACCESS_TARGET; } result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size); diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h index 3050815d7..72a2daef7 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h @@ -35,6 +35,7 @@ typedef enum lv_draw_sdl_composite_texture_id_t { LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1, + LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0, } lv_draw_sdl_composite_texture_id_t; /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c index c6782386e..59a9fc00f 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c @@ -22,6 +22,7 @@ #include "lv_draw_sdl_texture_cache.h" #include "lv_draw_sdl_composite.h" #include "lv_draw_sdl_rect.h" +#include "lv_draw_sdl_layer.h" /********************* * DEFINES @@ -123,11 +124,15 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t /* Coords will be translated so coords will start at (0,0) */ lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area; + bool has_composite = false; + if(!check_mask_simple_radius(&t_coords, &radius)) { - lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode, - &t_coords, &t_clip, &apply_area); + has_composite = lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode, + &t_coords, &t_clip, &apply_area); } + lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip); + SDL_Rect clip_rect, coords_rect; lv_area_to_sdl_rect(&t_clip, &clip_rect); lv_area_to_sdl_rect(&t_coords, &coords_rect); diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c index a067c8af4..b8c79ae4a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c @@ -19,6 +19,7 @@ #include "lv_draw_sdl_utils.h" #include "lv_draw_sdl_texture_cache.h" #include "lv_draw_sdl_composite.h" +#include "lv_draw_sdl_layer.h" /********************* * DEFINES @@ -77,6 +78,21 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter); + + /* draw placeholder */ + lv_area_t glyph_coords; + lv_draw_rect_dsc_t glyph_dsc; + lv_coord_t begin_x = pos_p->x + g.ofs_x; + lv_coord_t begin_y = pos_p->y + g.ofs_y; + lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h); + lv_draw_rect_dsc_init(&glyph_dsc); + glyph_dsc.bg_opa = LV_OPA_MIN; + glyph_dsc.outline_opa = LV_OPA_MIN; + glyph_dsc.shadow_opa = LV_OPA_MIN; + glyph_dsc.bg_img_opa = LV_OPA_MIN; + glyph_dsc.border_color = dsc->color; + glyph_dsc.border_width = 1; + draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords); } return; } @@ -119,8 +135,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t } lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area; - bool has_mask = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter, &t_clip, - &apply_area); + bool has_composite = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter, + &t_clip, &apply_area); + + lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_letter, &t_clip); /*If the letter is completely out of mask don't draw it*/ if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) { diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c new file mode 100644 index 000000000..48bc1b8f9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c @@ -0,0 +1,132 @@ +/** + * @file lv_draw_sdl_refr.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../core/lv_refr.h" + +#include "lv_draw_sdl.h" +#include "lv_draw_sdl_priv.h" +#include "lv_draw_sdl_composite.h" +#include "lv_draw_sdl_utils.h" +#include "lv_draw_sdl_layer.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags) +{ + lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; + SDL_Renderer * renderer = ctx->renderer; + + lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx; + + transform_ctx->flags = flags; + transform_ctx->orig_target = SDL_GetRenderTarget(renderer); + + lv_coord_t target_w = lv_area_get_width(&layer_ctx->area_full); + lv_coord_t target_h = lv_area_get_height(&layer_ctx->area_full); + + enum lv_draw_sdl_composite_texture_id_t texture_id = LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0 + + ctx->internals->transform_count; + transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h); + transform_ctx->target_rect.x = 0; + transform_ctx->target_rect.y = 0; + transform_ctx->target_rect.w = target_w; + transform_ctx->target_rect.h = target_h; + + SDL_SetTextureBlendMode(transform_ctx->target, SDL_BLENDMODE_BLEND); + SDL_SetRenderTarget(renderer, transform_ctx->target); + SDL_RenderClear(renderer); + + /* Set proper drawing context for transform layer */ + ctx->internals->transform_count += 1; + draw_ctx->buf_area = &layer_ctx->area_full; + draw_ctx->clip_area = &layer_ctx->area_full; + + return layer_ctx; +} + +void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + const lv_draw_img_dsc_t * draw_dsc) +{ + lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; + lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx; + + SDL_Renderer * renderer = ctx->renderer; + + SDL_Rect trans_rect; + + if(transform_ctx->flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { + lv_area_zoom_to_sdl_rect(&layer_ctx->area_act, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot); + } + else { + lv_area_zoom_to_sdl_rect(&layer_ctx->area_full, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot); + } + + SDL_SetRenderTarget(renderer, transform_ctx->orig_target); + + /*Render off-screen texture, transformed*/ + SDL_Rect clip_rect; + lv_area_to_sdl_rect(layer_ctx->original.clip_area, &clip_rect); + SDL_Point center = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y}; + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopyEx(renderer, transform_ctx->target, &transform_ctx->target_rect, &trans_rect, + draw_dsc->angle, ¢er, SDL_FLIP_NONE); + SDL_RenderSetClipRect(renderer, NULL); +} + +void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) +{ + lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; + ctx->internals->transform_count -= 1; +} + +void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area, + lv_area_t * coords, lv_area_t * clip) +{ + if(ctx->internals->transform_count == 0) { + return; + } + lv_area_t * area = ctx->base_draw.buf_area; + lv_area_move(coords, -area->x1, -area->y1); + lv_area_move(clip, -area->x1, -area->y1); + if(has_composite) { + lv_area_move(apply_area, -area->x1, -area->y1); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h new file mode 100644 index 000000000..b60303c47 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h @@ -0,0 +1,55 @@ +/** + * @file lv_draw_sdl_refr.h + * + */ + +#ifndef LV_TEMPL_H +#define LV_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sdl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct _lv_draw_sdl_layer_ctx_t { + lv_draw_layer_ctx_t base; + + SDL_Texture * orig_target; + SDL_Texture * target; + SDL_Rect target_rect; + lv_draw_layer_flags_t flags; +} lv_draw_sdl_layer_ctx_t; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + +void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * transform_ctx, + const lv_draw_img_dsc_t * draw_dsc); + +void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); + +void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area, + lv_area_t * coords, lv_area_t * clip); +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TEMPL_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h index 1f44c22ac..24a876218 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h @@ -35,6 +35,8 @@ typedef struct lv_draw_sdl_context_internals_t { lv_lru_t * texture_cache; SDL_Texture * mask; SDL_Texture * composition; + SDL_Texture * target_backup; + uint8_t transform_count; } lv_draw_sdl_context_internals_t; /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c index 4df113efb..a303ac764 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c @@ -21,7 +21,7 @@ #include "lv_draw_sdl_composite.h" #include "lv_draw_sdl_mask.h" #include "lv_draw_sdl_stack_blur.h" -#include "lv_draw_sdl_img.h" +#include "lv_draw_sdl_layer.h" /********************* * DEFINES @@ -124,7 +124,11 @@ void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * } /* Coords will be translated so coords will start at (0,0) */ lv_area_t t_coords = *coords, t_clip = *clip, apply_area, t_area; - lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, &apply_area); + bool has_composite = lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, + &apply_area); + + lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip); + bool has_content = _lv_area_intersect(&t_area, &t_coords, &t_clip); SDL_Rect clip_rect; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c index 58ff9f374..6845addf5 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c @@ -102,7 +102,7 @@ void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void } if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) { /* Managed texture doesn't count into cache size */ - LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format)); + LV_LOG_INFO("cache texture %p", texture); lv_lru_set(lru, key, key_length, value, 1); return; } diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk new file mode 100644 index 000000000..8ed00b015 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk @@ -0,0 +1,6 @@ +CSRCS += lv_gpu_stm32_dma2d.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c index 20344a567..4eb1940ef 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c @@ -103,6 +103,7 @@ void lv_draw_stm32_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) dma2d_draw_ctx->blend = lv_draw_stm32_dma2d_blend; // dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_stm32_dma2d_img_decoded; dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_stm32_dma2d_wait_cb; + dma2d_draw_ctx->base_draw.buffer_copy = lv_draw_stm32_dma2d_buffer_copy; } @@ -146,6 +147,14 @@ void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_ if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc); } +void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +{ + LV_UNUSED(draw_ctx); + lv_draw_stm32_dma2d_blend_map(dest_buf, dest_area, dest_stride, src_buf, src_stride, LV_OPA_MAX); +} + static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) @@ -213,8 +222,8 @@ static void lv_draw_stm32_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t DMA2D->FGMAR = (uint32_t)src_buf; DMA2D->FGOR = src_stride - dest_w; - DMA2D->OMAR = (uint32_t)src_buf; - DMA2D->OOR = src_stride - dest_w; + DMA2D->OMAR = (uint32_t)dest_buf; + DMA2D->OOR = dest_stride - dest_w; DMA2D->NLR = (dest_w << DMA2D_NLR_PL_Pos) | (dest_h << DMA2D_NLR_NL_Pos); /*start transfer*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h index 73054ca2d..fa7070e2a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h @@ -51,6 +51,10 @@ void lv_draw_stm32_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); + void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx); /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c index 21da4ee6b..1c0c6d4a2 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c @@ -51,8 +51,17 @@ void lv_draw_sw_init_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) draw_sw_ctx->base_draw.draw_img_decoded = lv_draw_sw_img_decoded; draw_sw_ctx->base_draw.draw_line = lv_draw_sw_line; draw_sw_ctx->base_draw.draw_polygon = lv_draw_sw_polygon; +#if LV_DRAW_COMPLEX + draw_sw_ctx->base_draw.draw_transform = lv_draw_sw_transform; +#endif draw_sw_ctx->base_draw.wait_for_finish = lv_draw_sw_wait_for_finish; + draw_sw_ctx->base_draw.buffer_copy = lv_draw_sw_buffer_copy; + draw_sw_ctx->base_draw.layer_init = lv_draw_sw_layer_create; + draw_sw_ctx->base_draw.layer_adjust = lv_draw_sw_layer_adjust; + draw_sw_ctx->base_draw.layer_blend = lv_draw_sw_layer_blend; + draw_sw_ctx->base_draw.layer_destroy = lv_draw_sw_layer_destroy; draw_sw_ctx->blend = lv_draw_sw_blend_basic; + draw_ctx->layer_instance_size = sizeof(lv_draw_sw_layer_ctx_t); } void lv_draw_sw_deinit_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) @@ -69,6 +78,31 @@ void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx) /*Nothing to wait for*/ } +void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +{ + LV_UNUSED(draw_ctx); + + lv_color_t * dest_bufc = dest_buf; + lv_color_t * src_bufc = src_buf; + + /*Got the first pixel of each buffer*/ + dest_bufc += dest_stride * dest_area->y1; + dest_bufc += dest_area->x1; + + src_bufc += src_stride * src_area->y1; + src_bufc += src_area->x1; + + uint32_t line_length = lv_area_get_width(dest_area) * sizeof(lv_color_t); + lv_coord_t y; + for(y = dest_area->y1; y <= dest_area->y2; y++) { + lv_memcpy(dest_bufc, src_bufc, line_length); + dest_bufc += dest_stride; + src_bufc += src_stride; + } +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h index cba5b480b..1618649cf 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h @@ -36,6 +36,13 @@ typedef struct { void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); } lv_draw_sw_ctx_t; +typedef struct { + lv_draw_layer_ctx_t base_draw; + + uint32_t buf_size_bytes: 31; + uint32_t has_alpha : 1; +} lv_draw_sw_layer_ctx_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -63,6 +70,25 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, con void lv_draw_sw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points, uint16_t point_cnt); +void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); + +void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, + lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); + +struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + +void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags); + +void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + const lv_draw_img_dsc_t * draw_dsc); + +void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); + /*********************** * GLOBAL VARIABLES ***********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk index 386d9ed81..4625cbcfc 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk @@ -1,13 +1,15 @@ CSRCS += lv_draw_sw.c CSRCS += lv_draw_sw_arc.c CSRCS += lv_draw_sw_blend.c +CSRCS += lv_draw_sw_dither.c +CSRCS += lv_draw_sw_gradient.c CSRCS += lv_draw_sw_img.c CSRCS += lv_draw_sw_letter.c CSRCS += lv_draw_sw_line.c -CSRCS += lv_draw_sw_rect.c CSRCS += lv_draw_sw_polygon.c -CSRCS += lv_draw_sw_gradient.c -CSRCS += lv_draw_sw_dither.c +CSRCS += lv_draw_sw_rect.c +CSRCS += lv_draw_sw_transform.c +CSRCS += lv_draw_sw_layer.c DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c index d020fdd4f..3ed62b6ef 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c @@ -97,8 +97,10 @@ void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, con /*Create inner the mask*/ int16_t mask_in_id = LV_MASK_ID_INV; lv_draw_mask_radius_param_t mask_in_param; + bool mask_in_param_valid = false; if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) { lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); + mask_in_param_valid = true; mask_in_id = lv_draw_mask_add(&mask_in_param, NULL); } @@ -115,7 +117,9 @@ void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, con if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id); lv_draw_mask_free_param(&mask_out_param); - lv_draw_mask_free_param(&mask_in_param); + if(mask_in_param_valid) { + lv_draw_mask_free_param(&mask_in_param); + } return; } @@ -162,7 +166,9 @@ void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, con lv_draw_mask_free_param(&mask_angle_param); lv_draw_mask_free_param(&mask_out_param); - lv_draw_mask_free_param(&mask_in_param); + if(mask_in_param_valid) { + lv_draw_mask_free_param(&mask_in_param); + } lv_draw_mask_remove_id(mask_angle_id); lv_draw_mask_remove_id(mask_out_id); @@ -237,7 +243,7 @@ static void draw_quarter_0(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } else if(q->start_quarter == 0 || q->end_quarter == 0) { @@ -252,7 +258,7 @@ static void draw_quarter_0(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } if(q->end_quarter == 0) { @@ -265,7 +271,7 @@ static void draw_quarter_0(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } } @@ -282,7 +288,7 @@ static void draw_quarter_0(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } q->draw_ctx->clip_area = clip_area_ori; @@ -304,7 +310,7 @@ static void draw_quarter_1(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } else if(q->start_quarter == 1 || q->end_quarter == 1) { @@ -319,7 +325,7 @@ static void draw_quarter_1(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } if(q->end_quarter == 1) { @@ -332,7 +338,7 @@ static void draw_quarter_1(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } } @@ -349,7 +355,7 @@ static void draw_quarter_1(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } q->draw_ctx->clip_area = clip_area_ori; @@ -371,7 +377,7 @@ static void draw_quarter_2(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } else if(q->start_quarter == 2 || q->end_quarter == 2) { @@ -386,7 +392,7 @@ static void draw_quarter_2(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } if(q->end_quarter == 2) { @@ -399,7 +405,7 @@ static void draw_quarter_2(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } } @@ -416,7 +422,7 @@ static void draw_quarter_2(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } q->draw_ctx->clip_area = clip_area_ori; @@ -438,7 +444,7 @@ static void draw_quarter_3(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } else if(q->start_quarter == 3 || q->end_quarter == 3) { @@ -453,7 +459,7 @@ static void draw_quarter_3(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } if(q->end_quarter == 3) { @@ -466,7 +472,7 @@ static void draw_quarter_3(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } } @@ -483,7 +489,7 @@ static void draw_quarter_3(quarter_draw_dsc_t * q) bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); if(ok) { q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, &quarter_area); + lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); } } diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c index 82d013888..428aba62c 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c @@ -25,8 +25,16 @@ static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stide); + LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride); + + +#if LV_COLOR_SCREEN_TRANSP +LV_ATTRIBUTE_FAST_MEM static void fill_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride); +#endif /*LV_COLOR_SCREEN_TRANSP*/ + #if LV_DRAW_COMPLEX static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode); @@ -38,6 +46,13 @@ static void map_set_px(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_co LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride); +#if LV_COLOR_SCREEN_TRANSP +LV_ATTRIBUTE_FAST_MEM static void map_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, + const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode); + +#endif /*LV_COLOR_SCREEN_TRANSP*/ + #if LV_DRAW_COMPLEX static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, @@ -55,22 +70,12 @@ static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color /********************** * MACROS **********************/ -#if LV_COLOR_SCREEN_TRANSP == 0 #define FILL_NORMAL_MASK_PX(color) \ if(*mask == LV_OPA_COVER) *dest_buf = color; \ else *dest_buf = lv_color_mix(color, *dest_buf, *mask); \ mask++; \ dest_buf++; -#else -#define FILL_NORMAL_MASK_PX(color) \ - if(*mask == LV_OPA_COVER) *dest_buf = color; \ - else if(disp->driver->screen_transp) lv_color_mix_with_alpha(*dest_buf, dest_buf->ch.alpha, color, *mask, dest_buf, &dest_buf->ch.alpha); \ - else *dest_buf = lv_color_mix(color, *dest_buf, *mask); \ - mask++; \ - dest_buf++; -#endif - #define MAP_NORMAL_MASK_PX(x) \ if(*mask_tmp_x) { \ if(*mask_tmp_x == LV_OPA_COVER) dest_buf[x] = src_buf[x]; \ @@ -78,15 +83,6 @@ static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color } \ mask_tmp_x++; -#define MAP_NORMAL_MASK_PX_SCR_TRANSP(x) \ - if(*mask_tmp_x) { \ - if(*mask_tmp_x == LV_OPA_COVER) dest_buf[x] = src_buf[x]; \ - else if(disp->driver->screen_transp) lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, \ - src_buf[x], *mask_tmp_x, &dest_buf[x], &dest_buf[x].ch.alpha); \ - else dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], *mask_tmp_x); \ - } \ - mask_tmp_x++; - /********************** * GLOBAL FUNCTIONS @@ -121,9 +117,19 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, cons lv_disp_t * disp = _lv_refr_get_disp_refreshing(); lv_color_t * dest_buf = draw_ctx->buf; if(disp->driver->set_px_cb == NULL) { - dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); + if(disp->driver->screen_transp == 0) { + dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); + } + else { + /*With LV_COLOR_DEPTH 16 it means ARGB8565 (3 bytes format)*/ + uint8_t * dest_buf8 = (uint8_t *) dest_buf; + dest_buf8 += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 += (blend_area.x1 - draw_ctx->buf_area->x1) * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf = (lv_color_t *)dest_buf8; + } } + const lv_color_t * src_buf = dsc->src_buf; lv_coord_t src_stride; if(src_buf) { @@ -137,7 +143,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, cons lv_coord_t mask_stride; if(mask) { mask_stride = lv_area_get_width(dsc->mask_area); - mask += mask_stride * (dsc->mask_area->y1 - blend_area.y1) + (dsc->mask_area->x1 - blend_area.x1); + mask += mask_stride * (blend_area.y1 - dsc->mask_area->y1) + (blend_area.x1 - dsc->mask_area->x1); } else { mask_stride = 0; @@ -154,21 +160,29 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, cons map_set_px(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride); } } - else if(dsc->src_buf == NULL) { - if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { +#if LV_COLOR_SCREEN_TRANSP + else if(disp->driver->screen_transp) { + if(dsc->src_buf == NULL) { + fill_argb(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride); + } + else { + map_argb(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride, dsc->blend_mode); + } + } +#endif + else if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(dsc->src_buf == NULL) { fill_normal(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride); } -#if LV_DRAW_COMPLEX else { - fill_blended(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride, dsc->blend_mode); - } -#endif - } - else { - if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { map_normal(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride); } + } + else { #if LV_DRAW_COMPLEX + if(dsc->src_buf == NULL) { + fill_blended(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride, dsc->blend_mode); + } else { map_blended(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride, dsc->blend_mode); } @@ -203,6 +217,8 @@ static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_ for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { if(mask[x]) { + + disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, blend_area->x1 + x, blend_area->y1 + y, color, (uint32_t)((uint32_t)opa * mask[x]) >> 8); } @@ -215,7 +231,6 @@ static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_ LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride) { - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); int32_t w = lv_area_get_width(dest_area); int32_t h = lv_area_get_height(dest_area); @@ -235,6 +250,14 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_ar lv_color_t last_dest_color = lv_color_black(); lv_color_t last_res_color = lv_color_mix(color, last_dest_color, opa); +#if LV_COLOR_MIX_ROUND_OFS == 0 && LV_COLOR_DEPTH == 16 + /*lv_color_mix work with an optimized algorithm with 16 bit color depth. + *However, it introduces some rounded error on opa. + *Introduce the same error here too to make lv_color_premult produces the same result */ + opa = (uint32_t)((uint32_t)opa + 4) >> 3; + opa = opa << 3; +#endif + uint16_t color_premult[3]; lv_color_premult(color, opa, color_premult); lv_opa_t opa_inv = 255 - opa; @@ -243,19 +266,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_ar for(x = 0; x < w; x++) { if(last_dest_color.full != dest_buf[x].full) { last_dest_color = dest_buf[x]; - -#if LV_COLOR_SCREEN_TRANSP - if(disp->driver->screen_transp) { - lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, color, opa, &last_res_color, - &last_res_color.ch.alpha); - } - else -#else - LV_UNUSED(disp); -#endif - { - last_res_color = lv_color_mix_premult(color_premult, dest_buf[x], opa_inv); - } + last_res_color = lv_color_mix_premult(color_premult, dest_buf[x], opa_inv); } dest_buf[x] = last_res_color; } @@ -335,17 +346,8 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_ar if(*mask != last_mask) opa_tmp = *mask == LV_OPA_COVER ? opa : (uint32_t)((uint32_t)(*mask) * opa) >> 8; if(*mask != last_mask || last_dest_color.full != dest_buf[x].full) { -#if LV_COLOR_SCREEN_TRANSP - if(disp->driver->screen_transp) { - lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, color, opa_tmp, &last_res_color, - &last_res_color.ch.alpha); - } - else -#endif - { - if(opa_tmp == LV_OPA_COVER) last_res_color = color; - else last_res_color = lv_color_mix(color, dest_buf[x], opa_tmp); - } + if(opa_tmp == LV_OPA_COVER) last_res_color = color; + else last_res_color = lv_color_mix(color, dest_buf[x], opa_tmp); last_mask = *mask; last_dest_color.full = dest_buf[x].full; } @@ -360,6 +362,161 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_ar } } +#if LV_COLOR_SCREEN_TRANSP +static inline void set_px_argb(uint8_t * buf, lv_color_t color, lv_opa_t opa) +{ + lv_color_t bg_color; + lv_color_t res_color; + lv_opa_t bg_opa = buf[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_DEPTH == 8 + bg_color.full = buf[0]; + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[1]); + if(buf[1] <= LV_OPA_MIN) return; + buf[0] = res_color.full; +#elif LV_COLOR_DEPTH == 16 + bg_color.full = buf[0] + (buf[1] << 8); + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[2]); + if(buf[2] <= LV_OPA_MIN) return; + buf[0] = res_color.full & 0xff; + buf[1] = res_color.full >> 8; +#elif LV_COLOR_DEPTH == 32 + bg_color = *((lv_color_t *)buf); + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[3]); + if(buf[3] <= LV_OPA_MIN) return; + buf[0] = res_color.ch.blue; + buf[1] = res_color.ch.green; + buf[2] = res_color.ch.red; +#endif +} + +static inline void set_px_argb_blend(uint8_t * buf, lv_color_t color, lv_opa_t opa, lv_color_t (*blend_fp)(lv_color_t, + lv_color_t, lv_opa_t)) +{ + static lv_color_t last_dest_color; + static lv_color_t last_src_color; + static lv_color_t last_res_color; + static uint32_t last_opa = 0xffff; /*Set to an invalid value for first*/ + + lv_color_t bg_color; + + /*Get the BG color*/ +#if LV_COLOR_DEPTH == 8 + if(buf[1] <= LV_OPA_MIN) return; + bg_color.full = buf[0]; +#elif LV_COLOR_DEPTH == 16 + if(buf[2] <= LV_OPA_MIN) return; + bg_color.full = buf[0] + (buf[1] << 8); +#elif LV_COLOR_DEPTH == 32 + if(buf[3] <= LV_OPA_MIN) return; + bg_color = *((lv_color_t *)buf); +#endif + + /*Get the result color*/ + if(last_dest_color.full != bg_color.full || last_src_color.full != color.full || last_opa != opa) { + last_dest_color = bg_color; + last_src_color = color; + last_opa = opa; + last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); + } + + /*Set the result color*/ +#if LV_COLOR_DEPTH == 8 + buf[0] = res_color.full; +#elif LV_COLOR_DEPTH == 16 + buf[0] = last_res_color.full & 0xff; + buf[1] = last_res_color.full >> 8; +#elif LV_COLOR_DEPTH == 32 + buf[0] = last_res_color.ch.blue; + buf[1] = last_res_color.ch.green; + buf[2] = last_res_color.ch.red; +#endif + +} + +LV_ATTRIBUTE_FAST_MEM static void fill_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, + lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride) +{ + uint8_t * dest_buf8 = (uint8_t *) dest_buf; + int32_t w = lv_area_get_width(dest_area); + int32_t h = lv_area_get_height(dest_area); + + int32_t x; + int32_t y; + + uint8_t ctmp[LV_IMG_PX_SIZE_ALPHA_BYTE]; + lv_memcpy(ctmp, &color, sizeof(lv_color_t)); + ctmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = opa; + + /*No mask*/ + if(mask == NULL) { + if(opa >= LV_OPA_MAX) { + for(x = 0; x < w; x++) { + lv_memcpy(dest_buf8, ctmp, LV_IMG_PX_SIZE_ALPHA_BYTE); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + + dest_buf8 += (dest_stride - w) * LV_IMG_PX_SIZE_ALPHA_BYTE; + + for(y = 1; y < h; y++) { + lv_memcpy(dest_buf8, (uint8_t *) dest_buf, w * LV_IMG_PX_SIZE_ALPHA_BYTE); + dest_buf8 += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + /*Has opacity*/ + else { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + set_px_argb(dest_buf8, color, opa); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + } + } + } + /*Masked*/ + else { + /*Only the mask matters*/ + if(opa >= LV_OPA_MAX) { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + set_px_argb(dest_buf8, color, *mask); + mask++; + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + } + } + /*With opacity*/ + else { + /*Buffer the result color to avoid recalculating the same color*/ + lv_opa_t last_mask = LV_OPA_TRANSP; + lv_opa_t opa_tmp = LV_OPA_TRANSP; + + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + if(*mask) { + if(*mask != last_mask) opa_tmp = *mask == LV_OPA_COVER ? opa : + (uint32_t)((uint32_t)(*mask) * opa) >> 8; + + set_px_argb(dest_buf8, color, opa_tmp); + } + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + mask++; + } + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + mask += (mask_stride - w); + } + } + } +} +#endif + #if LV_DRAW_COMPLEX static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride, @@ -477,10 +634,6 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are int32_t x; int32_t y; -#if LV_COLOR_SCREEN_TRANSP - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); -#endif - /*Simple fill (maybe with opacity), no masking*/ if(mask == NULL) { if(opa >= LV_OPA_MAX) { @@ -493,16 +646,7 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are else { for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { -#if LV_COLOR_SCREEN_TRANSP - if(disp->driver->screen_transp) { - lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, src_buf[x], opa, &dest_buf[x], - &dest_buf[x].ch.alpha); - } - else -#endif - { - dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa); - } + dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa); } dest_buf += dest_stride; src_buf += src_stride; @@ -523,11 +667,7 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are } #else for(x = 0; x < w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) { -#if LV_COLOR_SCREEN_TRANSP - MAP_NORMAL_MASK_PX_SCR_TRANSP(x) -#else MAP_NORMAL_MASK_PX(x) -#endif } uint32_t * mask32 = (uint32_t *)mask_tmp_x; @@ -541,17 +681,10 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are } else { mask_tmp_x = (const lv_opa_t *)mask32; -#if LV_COLOR_SCREEN_TRANSP - MAP_NORMAL_MASK_PX_SCR_TRANSP(x) - MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 1) - MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 2) - MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 3) -#else MAP_NORMAL_MASK_PX(x) MAP_NORMAL_MASK_PX(x + 1) MAP_NORMAL_MASK_PX(x + 2) MAP_NORMAL_MASK_PX(x + 3) -#endif } } mask32++; @@ -559,11 +692,7 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are mask_tmp_x = (const lv_opa_t *)mask32; for(; x < w ; x++) { -#if LV_COLOR_SCREEN_TRANSP - MAP_NORMAL_MASK_PX_SCR_TRANSP(x) -#else MAP_NORMAL_MASK_PX(x) -#endif } #endif dest_buf += dest_stride; @@ -577,16 +706,7 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are for(x = 0; x < w; x++) { if(mask[x]) { lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); -#if LV_COLOR_SCREEN_TRANSP - if(disp->driver->screen_transp) { - lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, src_buf[x], opa_tmp, - &dest_buf[x], &dest_buf[x].ch.alpha); - } - else -#endif - { - dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa_tmp); - } + dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa_tmp); } } dest_buf += dest_stride; @@ -596,6 +716,150 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_are } } } + + + +#if LV_COLOR_SCREEN_TRANSP +LV_ATTRIBUTE_FAST_MEM static void map_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, + const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode) + +{ + uint8_t * dest_buf8 = (uint8_t *) dest_buf; + + int32_t w = lv_area_get_width(dest_area); + int32_t h = lv_area_get_height(dest_area); + + int32_t x; + int32_t y; + + lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t); + switch(blend_mode) { + case LV_BLEND_MODE_ADDITIVE: + blend_fp = color_blend_true_color_additive; + break; + case LV_BLEND_MODE_SUBTRACTIVE: + blend_fp = color_blend_true_color_subtractive; + break; + case LV_BLEND_MODE_MULTIPLY: + blend_fp = color_blend_true_color_multiply; + break; + default: + blend_fp = NULL; + } + + /*Simple fill (maybe with opacity), no masking*/ + if(mask == NULL) { + if(opa >= LV_OPA_MAX) { + if(blend_fp == NULL && LV_COLOR_DEPTH == 32) { + for(y = 0; y < h; y++) { + lv_memcpy(dest_buf, src_buf, w * sizeof(lv_color_t)); + dest_buf += dest_stride; + src_buf += src_stride; + } + } + else { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + if(blend_fp == NULL) { + for(x = 0; x < w; x++) { + set_px_argb(dest_buf8, src_buf[x], LV_OPA_COVER); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + else { + for(x = 0; x < w; x++) { + set_px_argb_blend(dest_buf8, src_buf[x], LV_OPA_COVER, blend_fp); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + src_buf += src_stride; + } + } + } + /*No mask but opacity*/ + else { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + if(blend_fp == NULL) { + for(x = 0; x < w; x++) { + set_px_argb(dest_buf8, src_buf[x], opa); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + else { + for(x = 0; x < w; x++) { + set_px_argb_blend(dest_buf8, src_buf[x], opa, blend_fp); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + src_buf += src_stride; + } + } + } + /*Masked*/ + else { + /*Only the mask matters*/ + if(opa > LV_OPA_MAX) { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + if(blend_fp == NULL) { + for(x = 0; x < w; x++) { + set_px_argb(dest_buf8, src_buf[x], mask[x]); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + else { + for(x = 0; x < w; x++) { + set_px_argb_blend(dest_buf8, src_buf[x], mask[x], blend_fp); + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + src_buf += src_stride; + mask += mask_stride; + } + } + /*Handle opa and mask values too*/ + else { + uint8_t * dest_buf8_row = dest_buf8; + for(y = 0; y < h; y++) { + if(blend_fp == NULL) { + for(x = 0; x < w; x++) { + if(mask[x]) { + lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); + set_px_argb(dest_buf8, src_buf[x], opa_tmp); + } + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + else { + for(x = 0; x < w; x++) { + if(mask[x]) { + lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); + set_px_argb_blend(dest_buf8, src_buf[x], opa_tmp, blend_fp); + } + dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + } + dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; + dest_buf8 = dest_buf8_row; + src_buf += src_stride; + mask += mask_stride; + } + } + } +} +#endif + + #if LV_DRAW_COMPLEX static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, @@ -624,13 +888,21 @@ static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_c return; } + lv_color_t last_dest_color; + lv_color_t last_src_color; /*Simple fill (maybe with opacity), no masking*/ if(mask == NULL) { - /*The map will be indexed from `draw_area->x1` so compensate it.*/ - + last_dest_color = dest_buf[0]; + last_src_color = src_buf[0]; + lv_color_t last_res_color = blend_fp(last_src_color, last_dest_color, opa); for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { - dest_buf[x] = blend_fp(src_buf[x], dest_buf[x], opa); + if(last_src_color.full != src_buf[x].full || last_dest_color.full != dest_buf[x].full) { + last_dest_color = dest_buf[x]; + last_src_color = src_buf[x]; + last_res_color = blend_fp(last_src_color, last_dest_color, opa); + } + dest_buf[x] = last_res_color; } dest_buf += dest_stride; src_buf += src_stride; @@ -638,11 +910,21 @@ static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_c } /*Masked*/ else { + last_dest_color = dest_buf[0]; + last_src_color = src_buf[0]; + lv_opa_t last_opa = mask[0] >= LV_OPA_MAX ? opa : ((opa * mask[0]) >> 8); + lv_color_t last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { if(mask[x] == 0) continue; lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); - dest_buf[x] = blend_fp(src_buf[x], dest_buf[x], opa_tmp); + if(last_src_color.full != src_buf[x].full || last_dest_color.full != dest_buf[x].full || last_opa != opa_tmp) { + last_dest_color = dest_buf[x]; + last_src_color = src_buf[x]; + last_opa = opa_tmp; + last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); + } + dest_buf[x] = last_res_color; } dest_buf += dest_stride; src_buf += src_stride; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c index c5b32073e..4e4663266 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c @@ -21,23 +21,16 @@ #define GRAD_CONV(t, x) t = x #endif +#undef ALIGN #if defined(LV_ARCH_64) #define ALIGN(X) (((X) + 7) & ~7) #else #define ALIGN(X) (((X) + 3) & ~3) #endif -#define MAX_WIN_RES 1024 /**TODO: Find a way to get this information: max(horz_res, vert_res)*/ - -#if _DITHER_GRADIENT - #if LV_DITHER_ERROR_DIFFUSION == 1 - #define LV_DEFAULT_GRAD_CACHE_SIZE sizeof(lv_gradient_cache_t) + MAX_WIN_RES * sizeof(lv_grad_color_t) + MAX_WIN_RES * sizeof(lv_color_t) + MAX_WIN_RES * sizeof(lv_scolor24_t) - #else - #define LV_DEFAULT_GRAD_CACHE_SIZE sizeof(lv_gradient_cache_t) + MAX_WIN_RES * sizeof(lv_grad_color_t) + MAX_WIN_RES * sizeof(lv_color_t) - #endif /* LV_DITHER_ERROR_DIFFUSION */ -#else - #define LV_DEFAULT_GRAD_CACHE_SIZE sizeof(lv_gradient_cache_t) + MAX_WIN_RES * sizeof(lv_grad_color_t) -#endif /* _DITHER_GRADIENT */ +#if LV_GRAD_CACHE_DEF_SIZE != 0 && LV_GRAD_CACHE_DEF_SIZE < 256 + #error "LV_GRAD_CACHE_DEF_SIZE is too small" +#endif /********************** * STATIC PROTOTYPES @@ -94,8 +87,6 @@ static lv_grad_t * next_in_cache(lv_grad_t * item) if(item == NULL) return (lv_grad_t *)LV_GC_ROOT(_lv_grad_cache_mem); - if(item == NULL) - return NULL; size_t s = get_cache_item_size(item); /*Compute the size for this cache item*/ @@ -334,6 +325,8 @@ LV_ATTRIBUTE_FAST_MEM lv_grad_color_t lv_gradient_calculate(const lv_grad_dsc_t } } + LV_ASSERT(d != 0); + /*Then interpolate*/ frac -= min; lv_opa_t mix = (frac * 255) / d; diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c index 76c308419..9578bc7cc 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c @@ -17,6 +17,7 @@ /********************* * DEFINES *********************/ +#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) /********************** * TYPEDEFS @@ -25,6 +26,8 @@ /********************** * STATIC PROTOTYPES **********************/ +static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); /********************** * STATIC VARIABLES @@ -38,6 +41,7 @@ * GLOBAL FUNCTIONS **********************/ + LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf) { @@ -46,276 +50,248 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_c lv_area_copy(&draw_area, draw_ctx->clip_area); bool mask_any = lv_draw_mask_is_any(&draw_area); + bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; + lv_area_t blend_area; lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); + + lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); blend_dsc.opa = draw_dsc->opa; blend_dsc.blend_mode = draw_dsc->blend_mode; + blend_dsc.blend_area = &blend_area; /*The simplest case just copy the pixels into the draw_buf*/ - if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && - cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { - blend_dsc.blend_area = coords; + if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { blend_dsc.src_buf = (const lv_color_t *)src_buf; + + blend_dsc.blend_area = coords; lv_draw_sw_blend(draw_ctx, &blend_dsc); } + else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) { + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, coords, draw_ctx->clip_area)) return; + + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_area = coords; + blend_dsc.src_buf = NULL; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + + blend_dsc.blend_area = coords; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } +#if LV_COLOR_DEPTH == 16 + else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP) { + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + blend_dsc.src_buf = (const lv_color_t *)src_buf; + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_buf += sizeof(lv_color_t) * src_w * src_h; + blend_dsc.blend_area = coords; + blend_dsc.mask_area = coords; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } +#endif /*In the other cases every pixel need to be checked one-by-one*/ else { - //#if LV_DRAW_COMPLEX - /*The pixel size in byte is different if an alpha byte is added too*/ - uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); + blend_area.x1 = draw_ctx->clip_area->x1; + blend_area.x2 = draw_ctx->clip_area->x2; + blend_area.y1 = draw_ctx->clip_area->y1; + blend_area.y2 = draw_ctx->clip_area->y2; - /*Go to the first displayed pixel of the map*/ - int32_t src_stride = lv_area_get_width(coords); + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + lv_coord_t blend_h = lv_area_get_height(&blend_area); + lv_coord_t blend_w = lv_area_get_width(&blend_area); - lv_color_t c; - lv_color_t chroma_keyed_color = LV_COLOR_CHROMA_KEY; - uint32_t px_i = 0; - - const uint8_t * map_px; - - lv_coord_t draw_area_h = lv_area_get_height(&draw_area); - lv_coord_t draw_area_w = lv_area_get_width(&draw_area); - - lv_area_t blend_area; - blend_area.x1 = draw_area.x1; - blend_area.x2 = draw_area.x2; - blend_area.y1 = draw_area.y1; - blend_area.y2 = blend_area.y1; - blend_dsc.blend_area = &blend_area; - - bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; - /*Simple ARGB image. Handle it as special case because it's very common*/ - if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR_ALPHA && draw_dsc->recolor_opa == LV_OPA_TRANSP) { - uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); - uint32_t mask_buf_size = lv_area_get_size(&draw_area) > (uint32_t) hor_res ? hor_res : lv_area_get_size(&draw_area); - lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask_buf = mask_buf; - blend_dsc.mask_area = &blend_area; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - blend_dsc.src_buf = src_buf_rgb; - - const uint8_t * src_buf_tmp = src_buf; - src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte; - src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; - - int32_t x; - int32_t y; - for(y = 0; y < draw_area_h; y++) { - map_px = src_buf_tmp; - for(x = 0; x < draw_area_w; x++, map_px += px_size_byte, px_i++) { - lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - mask_buf[px_i] = px_opa; - if(px_opa) { -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - src_buf_rgb[px_i].full = map_px[0]; -#elif LV_COLOR_DEPTH == 16 - src_buf_rgb[px_i].full = map_px[0] + (map_px[1] << 8); -#elif LV_COLOR_DEPTH == 32 - src_buf_rgb[px_i].full = *((uint32_t *)map_px); -#endif - } -#if LV_COLOR_DEPTH == 32 - src_buf_rgb[px_i].ch.alpha = 0xFF; -#endif - } - - src_buf_tmp += src_stride * px_size_byte; - if(px_i + draw_area_w <= mask_buf_size) { - blend_area.y2 ++; - } - else { - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - blend_area.y1 = blend_area.y2 + 1; - blend_area.y2 = blend_area.y1; - - px_i = 0; - } - } - /*Flush the last part*/ - if(blend_area.y1 != blend_area.y2) { - blend_area.y2--; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(src_buf_rgb); + uint32_t max_buf_size = MAX_BUF_SIZE; + uint32_t blend_size = lv_area_get_size(&blend_area); + uint32_t buf_h; + uint32_t buf_w = blend_w; + if(blend_size <= max_buf_size) { + buf_h = blend_h; } - /*Most complicated case: transform or other mask or chroma keyed*/ else { - /*Build the image and a mask line-by-line*/ - uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); - uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area); - lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask_buf = mask_buf; - blend_dsc.mask_area = &blend_area; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - blend_dsc.src_buf = src_buf_rgb; + /*Round to full lines*/ + buf_h = max_buf_size / blend_w; + } - const uint8_t * src_buf_tmp = NULL; -#if LV_DRAW_COMPLEX - lv_img_transform_dsc_t trans_dsc; - lv_memset_00(&trans_dsc, sizeof(lv_img_transform_dsc_t)); + /*Create buffers and masks*/ + uint32_t buf_size = buf_w * buf_h; + + lv_color_t * rgb_buf = lv_mem_buf_get(buf_size * sizeof(lv_color_t)); + lv_opa_t * mask_buf = lv_mem_buf_get(buf_size); + blend_dsc.mask_buf = mask_buf; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + blend_dsc.src_buf = rgb_buf; + lv_coord_t y_last = blend_area.y2; + blend_area.y2 = blend_area.y1 + buf_h - 1; + + lv_draw_mask_res_t mask_res_def = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || + draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? + LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; + blend_dsc.mask_res = mask_res_def; + + while(blend_area.y1 <= y_last) { + /*Apply transformations if any or separate the channels*/ + lv_area_t transform_area; + lv_area_copy(&transform_area, &blend_area); + lv_area_move(&transform_area, -coords->x1, -coords->y1); if(transform) { - trans_dsc.cfg.angle = draw_dsc->angle; - trans_dsc.cfg.zoom = draw_dsc->zoom; - trans_dsc.cfg.src = src_buf; - trans_dsc.cfg.src_w = src_stride; - trans_dsc.cfg.src_h = lv_area_get_height(coords); - trans_dsc.cfg.cf = cf; - trans_dsc.cfg.pivot_x = draw_dsc->pivot.x; - trans_dsc.cfg.pivot_y = draw_dsc->pivot.y; - trans_dsc.cfg.color = draw_dsc->recolor; - trans_dsc.cfg.antialias = draw_dsc->antialias; - - _lv_img_buf_transform_init(&trans_dsc); + lv_draw_transform(draw_ctx, &transform_area, src_buf, src_w, src_h, src_w, + draw_dsc, cf, rgb_buf, mask_buf); } else { - src_buf_tmp = src_buf; - src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte; - src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; - } -#endif - uint16_t recolor_premult[3] = {0}; - lv_opa_t recolor_opa_inv = 255 - draw_dsc->recolor_opa; - if(draw_dsc->recolor_opa != 0) { - lv_color_premult(draw_dsc->recolor, draw_dsc->recolor_opa, recolor_premult); + convert_cb(&transform_area, src_buf, src_w, src_h, src_w, draw_dsc, cf, rgb_buf, mask_buf); } - blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || - draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - - /*Prepare the `mask_buf`if there are other masks*/ + /*Apply recolor*/ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + uint16_t premult_v[3]; + lv_opa_t recolor_opa = draw_dsc->recolor_opa; + lv_color_t recolor = draw_dsc->recolor; + lv_color_premult(recolor, recolor_opa, premult_v); + recolor_opa = 255 - recolor_opa; + uint32_t i; + for(i = 0; i < buf_size; i++) { + rgb_buf[i] = lv_color_mix_premult(premult_v, rgb_buf[i], recolor_opa); + } + } +#if LV_DRAW_COMPLEX + /*Apply the masks if any*/ if(mask_any) { - lv_memset_ff(mask_buf, mask_buf_size); - } + lv_coord_t y; + lv_opa_t * mask_buf_tmp = mask_buf; + for(y = blend_area.y1; y <= blend_area.y2; y++) { + lv_draw_mask_res_t mask_res_line; + mask_res_line = lv_draw_mask_apply(mask_buf_tmp, blend_area.x1, y, blend_w); - int32_t x; - int32_t y; -#if LV_DRAW_COMPLEX - int32_t rot_y = blend_area.y1 - coords->y1; -#endif - for(y = 0; y < draw_area_h; y++) { - map_px = src_buf_tmp; -#if LV_DRAW_COMPLEX - uint32_t px_i_start = px_i; - int32_t rot_x = blend_area.x1 - coords->x1; -#endif - - for(x = 0; x < draw_area_w; x++, px_i++, map_px += px_size_byte) { - -#if LV_DRAW_COMPLEX - if(transform) { - - /*Transform*/ - bool ret; - ret = _lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y); - if(ret == false) { - mask_buf[px_i] = LV_OPA_TRANSP; - continue; - } - else { - mask_buf[px_i] = trans_dsc.res.opa; - c.full = trans_dsc.res.color.full; - } - } - /*No transform*/ - else -#endif - { - if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - mask_buf[px_i] = px_opa; - if(px_opa == 0) { -#if LV_COLOR_DEPTH == 32 - src_buf_rgb[px_i].full = 0; -#endif - continue; - } - } - else { - mask_buf[px_i] = 0xFF; - } - -#if LV_COLOR_DEPTH == 1 - c.full = map_px[0]; -#elif LV_COLOR_DEPTH == 8 - c.full = map_px[0]; -#elif LV_COLOR_DEPTH == 16 - c.full = map_px[0] + (map_px[1] << 8); -#elif LV_COLOR_DEPTH == 32 - c.full = *((uint32_t *)map_px); - c.ch.alpha = 0xFF; -#endif - if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - if(c.full == chroma_keyed_color.full) { - mask_buf[px_i] = LV_OPA_TRANSP; -#if LV_COLOR_DEPTH == 32 - src_buf_rgb[px_i].full = 0; -#endif - continue; - } - } - - } - if(draw_dsc->recolor_opa != 0) { - c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv); - } - - src_buf_rgb[px_i].full = c.full; - } -#if LV_DRAW_COMPLEX - /*Apply the masks if any*/ - if(mask_any) { - lv_draw_mask_res_t mask_res_sub; - mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, blend_area.x1, - y + draw_area.y1, draw_area_w); - if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf + px_i_start, draw_area_w); + if(mask_res_line == LV_DRAW_MASK_RES_TRANSP) { + lv_memset_00(mask_buf_tmp, blend_w); blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } - else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { + else if(mask_res_line == LV_DRAW_MASK_RES_CHANGED) { blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } + mask_buf_tmp += blend_w; } + } #endif - src_buf_tmp += src_stride * px_size_byte; - if(px_i + draw_area_w < mask_buf_size) { - blend_area.y2 ++; - } - else { - lv_draw_sw_blend(draw_ctx, &blend_dsc); + /*Blend*/ + lv_draw_sw_blend(draw_ctx, &blend_dsc); - blend_area.y1 = blend_area.y2 + 1; - blend_area.y2 = blend_area.y1; - - px_i = 0; - blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || - draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - - /*Prepare the `mask_buf`if there are other masks*/ - if(mask_any) { - lv_memset_ff(mask_buf, mask_buf_size); - } - } - } - - /*Flush the last part*/ - if(blend_area.y1 != blend_area.y2) { - blend_area.y2--; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(src_buf_rgb); + /*Go the the next lines*/ + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1 + buf_h - 1; + if(blend_area.y2 > y_last) blend_area.y2 = y_last; } + + lv_mem_buf_release(mask_buf); + lv_mem_buf_release(rgb_buf); } } /********************** * STATIC FUNCTIONS **********************/ + +/* Separate the image channels to RGB and Alpha to match LV_COLOR_DEPTH settings*/ +static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +{ + LV_UNUSED(draw_dsc); + LV_UNUSED(src_h); + LV_UNUSED(src_w); + + const uint8_t * src_tmp8 = (const uint8_t *)src_buf; + lv_coord_t y; + lv_coord_t x; + + if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t px_cnt = lv_area_get_size(dest_area); + lv_memset_ff(abuf, px_cnt); + + src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); + uint32_t dest_w = lv_area_get_width(dest_area); + uint32_t dest_w_byte = dest_w * sizeof(lv_color_t); + + lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); + lv_color_t * cbuf_tmp = cbuf; + for(y = dest_area->y1; y <= dest_area->y2; y++) { + lv_memcpy(cbuf_tmp, src_tmp8, dest_w_byte); + src_tmp8 += src_stride_byte; + cbuf_tmp += dest_w; + } + + /*Make "holes" for with Chroma keying*/ + if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t i; + lv_color_t chk = LV_COLOR_CHROMA_KEY; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + uint8_t * cbuf_uint = (uint8_t *)cbuf; + uint8_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 16 + uint16_t * cbuf_uint = (uint16_t *)cbuf; + uint16_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 32 + uint32_t * cbuf_uint = (uint32_t *)cbuf; + uint32_t chk_v = chk.full; +#endif + for(i = 0; i < px_cnt; i++) { + if(chk_v == cbuf_uint[i]) abuf[i] = 0x00; + } + } + } + else if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + src_tmp8 += (src_stride * dest_area->y1 * LV_IMG_PX_SIZE_ALPHA_BYTE) + dest_area->x1 * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t src_new_line_step_px = (src_stride - lv_area_get_width(dest_area)); + lv_coord_t src_new_line_step_byte = src_new_line_step_px * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + for(y = 0; y < dest_h; y++) { + for(x = 0; x < dest_w; x++) { + abuf[x] = src_tmp8[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + cbuf[x].full = *src_tmp8; +#elif LV_COLOR_DEPTH == 16 + cbuf[x].full = *src_tmp8 + ((*(src_tmp8 + 1)) << 8); +#elif LV_COLOR_DEPTH == 32 + cbuf[x] = *((lv_color_t *) src_tmp8); + cbuf[x].ch.alpha = 0xff; +#endif + src_tmp8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + + } + cbuf += dest_w; + abuf += dest_w; + src_tmp8 += src_new_line_step_byte; + } + } + else if(cf == LV_IMG_CF_RGB565A8) { + src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); + + lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); + + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + for(y = 0; y < dest_h; y++) { + lv_memcpy(cbuf, src_tmp8, dest_w * sizeof(lv_color_t)); + cbuf += dest_w; + src_tmp8 += src_stride_byte; + } + + src_tmp8 = (const uint8_t *)src_buf; + src_tmp8 += sizeof(lv_color_t) * src_w * src_h; + src_tmp8 += src_stride * dest_area->y1 + dest_area->x1; + for(y = 0; y < dest_h; y++) { + lv_memcpy(abuf, src_tmp8, dest_w); + abuf += dest_w; + src_tmp8 += src_stride; + } + } +} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c new file mode 100644 index 000000000..644012fee --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c @@ -0,0 +1,150 @@ +/** + * @file lv_draw_sw_layer.h + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#include "../../hal/lv_hal_disp.h" +#include "../../misc/lv_area.h" +#include "../../core/lv_refr.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + + +struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags) +{ + if(LV_COLOR_SCREEN_TRANSP == 0 && (flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA)) { + LV_LOG_WARN("Rendering this widget needs LV_COLOR_SCREEN_TRANSP 1"); + return NULL; + } + + lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; + uint32_t px_size = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); + if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { + layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_BUF_SIZE; + uint32_t full_size = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size; + if(layer_sw_ctx->buf_size_bytes > full_size) layer_sw_ctx->buf_size_bytes = full_size; + layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); + if(layer_sw_ctx->base_draw.buf == NULL) { + LV_LOG_WARN("Cannot allocate %"LV_PRIu32" bytes for layer buffer. Allocating %"LV_PRIu32" bytes instead. (Reduced performance)", + (uint32_t)layer_sw_ctx->buf_size_bytes, (uint32_t)LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE * px_size); + layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE; + layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); + if(layer_sw_ctx->base_draw.buf == NULL) { + return NULL; + } + } + layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full; + layer_sw_ctx->base_draw.area_act.y2 = layer_sw_ctx->base_draw.area_full.y1; + lv_coord_t w = lv_area_get_width(&layer_sw_ctx->base_draw.area_act); + layer_sw_ctx->base_draw.max_row_with_alpha = layer_sw_ctx->buf_size_bytes / w / LV_IMG_PX_SIZE_ALPHA_BYTE; + layer_sw_ctx->base_draw.max_row_with_no_alpha = layer_sw_ctx->buf_size_bytes / w / sizeof(lv_color_t); + } + else { + layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full; + layer_sw_ctx->buf_size_bytes = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size; + layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); + lv_memset_00(layer_sw_ctx->base_draw.buf, layer_sw_ctx->buf_size_bytes); + layer_sw_ctx->has_alpha = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0; + if(layer_sw_ctx->base_draw.buf == NULL) { + return NULL; + } + + draw_ctx->buf = layer_sw_ctx->base_draw.buf; + draw_ctx->buf_area = &layer_sw_ctx->base_draw.area_act; + draw_ctx->clip_area = &layer_sw_ctx->base_draw.area_act; + + lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); + disp_refr->driver->screen_transp = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0; + } + + return layer_ctx; +} + +void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + lv_draw_layer_flags_t flags) +{ + + lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; + lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); + if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) { + lv_memset_00(layer_ctx->buf, layer_sw_ctx->buf_size_bytes); + layer_sw_ctx->has_alpha = 1; + disp_refr->driver->screen_transp = 1; + } + else { + layer_sw_ctx->has_alpha = 0; + disp_refr->driver->screen_transp = 0; + } + + draw_ctx->buf = layer_ctx->buf; + draw_ctx->buf_area = &layer_ctx->area_act; + draw_ctx->clip_area = &layer_ctx->area_act; +} + +void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, + const lv_draw_img_dsc_t * draw_dsc) +{ + lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; + + lv_img_dsc_t img; + img.data = draw_ctx->buf; + img.header.always_zero = 0; + img.header.w = lv_area_get_width(draw_ctx->buf_area); + img.header.h = lv_area_get_height(draw_ctx->buf_area); + img.header.cf = layer_sw_ctx->has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; + lv_img_cache_invalidate_src(&img); + + /*Restore the original draw_ctx*/ + draw_ctx->buf = layer_ctx->original.buf; + draw_ctx->buf_area = layer_ctx->original.buf_area; + draw_ctx->clip_area = layer_ctx->original.clip_area; + lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); + disp_refr->driver->screen_transp = layer_ctx->original.screen_transp; + + /*Blend the layer*/ + lv_draw_img(draw_ctx, draw_dsc, &layer_ctx->area_act, &img); + lv_draw_wait_for_finish(draw_ctx); +} + +void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) +{ + LV_UNUSED(draw_ctx); + + lv_mem_free(layer_ctx->buf); +} + + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c index e7578cffb..9522888c9 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c @@ -97,13 +97,30 @@ void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc { lv_font_glyph_dsc_t g; bool g_ret = lv_font_get_glyph_dsc(dsc->font, &g, letter, '\0'); - if(g_ret == false) { + if(g_ret == false) { /*Add warning if the dsc is not found *but do not print warning for non printable ASCII chars (e.g. '\n')*/ if(letter >= 0x20 && letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", (unsigned int)letter); + LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" PRIX32, letter); + +#if LV_USE_FONT_PLACEHOLDER + /* draw placeholder */ + lv_area_t glyph_coords; + lv_draw_rect_dsc_t glyph_dsc; + lv_coord_t begin_x = pos_p->x + g.ofs_x; + lv_coord_t begin_y = pos_p->y + g.ofs_y; + lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h); + lv_draw_rect_dsc_init(&glyph_dsc); + glyph_dsc.bg_opa = LV_OPA_MIN; + glyph_dsc.outline_opa = LV_OPA_MIN; + glyph_dsc.shadow_opa = LV_OPA_MIN; + glyph_dsc.bg_img_opa = LV_OPA_MIN; + glyph_dsc.border_color = dsc->color; + glyph_dsc.border_width = 1; + draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords); +#endif } return; } @@ -157,6 +174,24 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_draw_ctx_t * draw_ctx, c uint32_t shades; if(bpp == 3) bpp = 4; +#if LV_USE_IMGFONT + if(bpp == LV_IMGFONT_BPP) { //is imgfont + lv_area_t fill_area; + fill_area.x1 = pos->x; + fill_area.y1 = pos->y; + fill_area.x2 = pos->x + g->box_w - 1; + fill_area.y2 = pos->y + g->box_h - 1; + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.angle = 0; + img_dsc.zoom = LV_IMG_ZOOM_NONE; + img_dsc.opa = dsc->opa; + img_dsc.blend_mode = dsc->blend_mode; + lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p); + return; + } +#endif + switch(bpp) { case 1: bpp_opa_table_p = _lv_bpp1_opa_table; @@ -408,7 +443,7 @@ static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_ #endif lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(&blend_dsc)); + lv_memset_00(&blend_dsc, sizeof(blend_dsc)); blend_dsc.blend_area = &map_area; blend_dsc.mask_area = &map_area; blend_dsc.src_buf = color_buf; @@ -507,6 +542,7 @@ static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_ map_area.y2 ++; } else { + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; lv_draw_sw_blend(draw_ctx, &blend_dsc); map_area.y1 = map_area.y2 + 1; @@ -526,6 +562,7 @@ static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_ /*Flush the last part*/ if(map_area.y1 != map_area.y2) { map_area.y2--; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; lv_draw_sw_blend(draw_ctx, &blend_dsc); } diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c index d94431b0c..2b2ea9820 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c @@ -128,7 +128,6 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co if(!mask_any && dsc->radius == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { blend_dsc.blend_area = &bg_coords; blend_dsc.opa = dsc->bg_opa; - lv_draw_sw_blend(draw_ctx, &blend_dsc); return; } @@ -333,6 +332,14 @@ static void draw_bg_img(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc if(dsc->bg_img_src == NULL) return; if(dsc->bg_img_opa <= LV_OPA_MIN) return; + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, coords, draw_ctx->clip_area)) { + return; + } + + const lv_area_t * clip_area_ori = draw_ctx->clip_area; + draw_ctx->clip_area = &clip_area; + lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); if(src_type == LV_IMG_SRC_SYMBOL) { lv_point_t size; @@ -353,43 +360,45 @@ static void draw_bg_img(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc else { lv_img_header_t header; lv_res_t res = lv_img_decoder_get_info(dsc->bg_img_src, &header); - if(res != LV_RES_OK) { - LV_LOG_WARN("Couldn't read the background image"); - return; - } + if(res == LV_RES_OK) { + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.blend_mode = dsc->blend_mode; + img_dsc.recolor = dsc->bg_img_recolor; + img_dsc.recolor_opa = dsc->bg_img_recolor_opa; + img_dsc.opa = dsc->bg_img_opa; - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.blend_mode = dsc->blend_mode; - img_dsc.recolor = dsc->bg_img_recolor; - img_dsc.recolor_opa = dsc->bg_img_recolor_opa; - img_dsc.opa = dsc->bg_img_opa; - - /*Center align*/ - if(dsc->bg_img_tiled == false) { - lv_area_t area; - area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; - area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; - area.x2 = area.x1 + header.w - 1; - area.y2 = area.y1 + header.h - 1; - - lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); - } - else { - lv_area_t area; - area.y1 = coords->y1; - area.y2 = area.y1 + header.h - 1; - - for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { - - area.x1 = coords->x1; + /*Center align*/ + if(dsc->bg_img_tiled == false) { + lv_area_t area; + area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; + area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; area.x2 = area.x1 + header.w - 1; - for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { - lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); + area.y2 = area.y1 + header.h - 1; + + lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); + } + else { + lv_area_t area; + area.y1 = coords->y1; + area.y2 = area.y1 + header.h - 1; + + for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { + + area.x1 = coords->x1; + area.x2 = area.x1 + header.w - 1; + for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { + lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); + } } } } + else { + LV_LOG_WARN("Couldn't read the background image"); + } } + + draw_ctx->clip_area = clip_area_ori; } static void draw_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c new file mode 100644 index 000000000..80b1e6dea --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c @@ -0,0 +1,496 @@ +/** + * @file lv_draw_sw_tranform.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_area.h" +#include "../../core/lv_refr.h" + +#if LV_DRAW_COMPLEX +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + int32_t x_in; + int32_t y_in; + int32_t x_out; + int32_t y_out; + int32_t sinma; + int32_t cosma; + int32_t zoom; + int32_t angle; + int32_t pivot_x_256; + int32_t pivot_y_256; + lv_point_t pivot; +} point_transform_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +/** + * Transform a point with 1/256 precision (the output coordinates are upscaled by 256) + * @param t pointer to n initialized `point_transform_dsc_t` structure + * @param xin X coordinate to rotate + * @param yin Y coordinate to rotate + * @param xout upscaled, transformed X + * @param yout upscaled, transformed Y + */ +static void transform_point_upscaled(point_transform_dsc_t * t, int32_t xin, int32_t yin, int32_t * xout, + int32_t * yout); + +static void argb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); + +static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf); + +#if LV_COLOR_DEPTH == 16 +static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); +#endif + +static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, + lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +{ + LV_UNUSED(draw_ctx); + + point_transform_dsc_t tr_dsc; + tr_dsc.angle = -draw_dsc->angle; + tr_dsc.zoom = (256 * 256) / draw_dsc->zoom; + tr_dsc.pivot = draw_dsc->pivot; + + int32_t angle_low = tr_dsc.angle / 10; + int32_t angle_high = angle_low + 1; + int32_t angle_rem = tr_dsc.angle - (angle_low * 10); + + int32_t s1 = lv_trigo_sin(angle_low); + int32_t s2 = lv_trigo_sin(angle_high); + + int32_t c1 = lv_trigo_sin(angle_low + 90); + int32_t c2 = lv_trigo_sin(angle_high + 90); + + tr_dsc.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; + tr_dsc.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; + tr_dsc.sinma = tr_dsc.sinma >> (LV_TRIGO_SHIFT - 10); + tr_dsc.cosma = tr_dsc.cosma >> (LV_TRIGO_SHIFT - 10); + tr_dsc.pivot_x_256 = tr_dsc.pivot.x * 256; + tr_dsc.pivot_y_256 = tr_dsc.pivot.y * 256; + + lv_coord_t dest_w = lv_area_get_width(dest_area); + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t y; + for(y = 0; y < dest_h; y++) { + int32_t xs1_ups, ys1_ups, xs2_ups, ys2_ups; + + transform_point_upscaled(&tr_dsc, dest_area->x1, dest_area->y1 + y, &xs1_ups, &ys1_ups); + transform_point_upscaled(&tr_dsc, dest_area->x2, dest_area->y1 + y, &xs2_ups, &ys2_ups); + + int32_t xs_diff = xs2_ups - xs1_ups; + int32_t ys_diff = ys2_ups - ys1_ups; + int32_t xs_step_256 = 0; + int32_t ys_step_256 = 0; + if(dest_w > 1) { + xs_step_256 = (256 * xs_diff) / (dest_w - 1); + ys_step_256 = (256 * ys_diff) / (dest_w - 1); + } + int32_t xs_ups = xs1_ups; + int32_t ys_ups = ys1_ups; + + if(draw_dsc->antialias == 0) { + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + argb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + break; + case LV_IMG_CF_TRUE_COLOR: + case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: + rgb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, cf); + break; + +#if LV_COLOR_DEPTH == 16 + case LV_IMG_CF_RGB565A8: + rgb565a8_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + break; +#endif + default: + break; + } + } + else { + argb_and_rgb_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, cf); + } + + cbuf += dest_w; + abuf += dest_w; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + lv_disp_t * d = _lv_refr_get_disp_refreshing(); + lv_color_t ck = d->driver->color_chroma_key; + + lv_memset_ff(abuf, x_end); + + lv_coord_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0x00; + } + else { + +#if LV_COLOR_DEPTH == 8 + const uint8_t * src_tmp = src; + src_tmp += ys_int * src_stride + xs_int; + cbuf[x].full = src_tmp[0]; +#elif LV_COLOR_DEPTH == 16 + const lv_color_t * src_tmp = (const lv_color_t *)src; + src_tmp += ys_int * src_stride + xs_int; + cbuf[x] = *src_tmp; +#elif LV_COLOR_DEPTH == 32 + const uint8_t * src_tmp = src; + src_tmp += (ys_int * src_stride * sizeof(lv_color_t)) + xs_int * sizeof(lv_color_t); + cbuf[x].full = *((uint32_t *)src_tmp); +#endif + } + if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED && cbuf[x].full == ck.full) { + abuf[x] = 0x00; + } + } +} + +static void argb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + + lv_coord_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0; + } + else { + const uint8_t * src_tmp = src; + src_tmp += (ys_int * src_stride * LV_IMG_PX_SIZE_ALPHA_BYTE) + xs_int * LV_IMG_PX_SIZE_ALPHA_BYTE; + +#if LV_COLOR_DEPTH == 8 + cbuf[x].full = src_tmp[0]; +#elif LV_COLOR_DEPTH == 16 + cbuf[x].full = src_tmp[0] + (src_tmp[1] << 8); +#elif LV_COLOR_DEPTH == 32 + cbuf[x].full = *((uint32_t *)src_tmp); +#endif + abuf[x] = src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + } + } +} + +#if LV_COLOR_DEPTH == 16 +static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + + lv_coord_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0; + } + else { + const lv_color_t * src_tmp = (const lv_color_t *)src; + src_tmp += ys_int * src_stride + xs_int; + cbuf[x] = *src_tmp; + + const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); + a_tmp += ys_int * src_stride + xs_int; + abuf[x] = *a_tmp; + } + } +} +#endif + + +static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + bool has_alpha; + int32_t px_size; + lv_color_t ck = {0}; + switch(cf) { + case LV_IMG_CF_TRUE_COLOR: + has_alpha = false; + px_size = sizeof(lv_color_t); + break; + case LV_IMG_CF_TRUE_COLOR_ALPHA: + has_alpha = true; + px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; + break; + case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: { + has_alpha = true; + px_size = sizeof(lv_color_t); + lv_disp_t * d = _lv_refr_get_disp_refreshing(); + ck = d->driver->color_chroma_key; + break; + } +#if LV_COLOR_DEPTH == 16 + case LV_IMG_CF_RGB565A8: + has_alpha = true; + px_size = sizeof(lv_color_t); + break; +#endif + default: + return; + } + + lv_coord_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + + /*Fully out of the image*/ + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0x00; + continue; + } + + /*Get the direction the hor and ver neighbor + *`fract` will be in range of 0x00..0xFF and `next` (+/-1) indicates the direction*/ + int32_t xs_fract = xs_ups & 0xFF; + int32_t ys_fract = ys_ups & 0xFF; + + int32_t x_next; + int32_t y_next; + if(xs_fract < 0x80) { + x_next = -1; + xs_fract = (0x7F - xs_fract) * 2; + } + else { + x_next = 1; + xs_fract = (xs_fract - 0x80) * 2; + } + if(ys_fract < 0x80) { + y_next = -1; + ys_fract = (0x7F - ys_fract) * 2; + } + else { + y_next = 1; + ys_fract = (ys_fract - 0x80) * 2; + } + + const uint8_t * src_tmp = src; + src_tmp += (ys_int * src_stride * px_size) + xs_int * px_size; + + + if(xs_int + x_next >= 0 && + xs_int + x_next <= src_w - 1 && + ys_int + y_next >= 0 && + ys_int + y_next <= src_h - 1) { + + const uint8_t * px_base = src_tmp; + const uint8_t * px_hor = src_tmp + x_next * px_size; + const uint8_t * px_ver = src_tmp + y_next * src_stride * px_size; + lv_color_t c_base; + lv_color_t c_ver; + lv_color_t c_hor; + + if(has_alpha) { + lv_opa_t a_base; + lv_opa_t a_ver; + lv_opa_t a_hor; + if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + a_base = px_base[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + a_ver = px_ver[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + a_hor = px_hor[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + } +#if LV_COLOR_DEPTH == 16 + else if(cf == LV_IMG_CF_RGB565A8) { + const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); + a_base = *(a_tmp + (ys_int * src_stride) + xs_int); + a_hor = *(a_tmp + (ys_int * src_stride) + xs_int + x_next); + a_ver = *(a_tmp + ((ys_int + y_next) * src_stride) + xs_int); + } +#endif + else if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + if(((lv_color_t *)px_base)->full == ck.full || + ((lv_color_t *)px_ver)->full == ck.full || + ((lv_color_t *)px_hor)->full == ck.full) { + abuf[x] = 0x00; + continue; + } + else { + a_base = 0xff; + a_ver = 0xff; + a_hor = 0xff; + } + } + else { + a_base = 0xff; + a_ver = 0xff; + a_hor = 0xff; + } + + if(a_ver != a_base) a_ver = ((a_ver * ys_fract) + (a_base * (0x100 - ys_fract))) >> 8; + if(a_hor != a_base) a_hor = ((a_hor * xs_fract) + (a_base * (0x100 - xs_fract))) >> 8; + abuf[x] = (a_ver + a_hor) >> 1; + + if(abuf[x] == 0x00) continue; + +#if LV_COLOR_DEPTH == 8 + c_base.full = px_base[0]; + c_ver.full = px_ver[0]; + c_hor.full = px_hor[0]; +#elif LV_COLOR_DEPTH == 16 + c_base.full = px_base[0] + (px_base[1] << 8); + c_ver.full = px_ver[0] + (px_ver[1] << 8); + c_hor.full = px_hor[0] + (px_hor[1] << 8); +#elif LV_COLOR_DEPTH == 32 + c_base.full = *((uint32_t *)px_base); + c_ver.full = *((uint32_t *)px_ver); + c_hor.full = *((uint32_t *)px_hor); +#endif + } + /*No alpha channel -> RGB*/ + else { + c_base = *((const lv_color_t *) px_base); + c_hor = *((const lv_color_t *) px_hor); + c_ver = *((const lv_color_t *) px_ver); + abuf[x] = 0xff; + } + + if(c_base.full == c_ver.full && c_base.full == c_hor.full) { + cbuf[x] = c_base; + } + else { + c_ver = lv_color_mix(c_ver, c_base, ys_fract); + c_hor = lv_color_mix(c_hor, c_base, xs_fract); + cbuf[x] = lv_color_mix(c_hor, c_ver, LV_OPA_50); + } + } + /*Partially out of the image*/ + else { +#if LV_COLOR_DEPTH == 8 + cbuf[x].full = src_tmp[0]; +#elif LV_COLOR_DEPTH == 16 + cbuf[x].full = src_tmp[0] + (src_tmp[1] << 8); +#elif LV_COLOR_DEPTH == 32 + cbuf[x].full = *((uint32_t *)src_tmp); +#endif + lv_opa_t a; + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + a = src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + break; + case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: + a = cbuf[x].full == ck.full ? 0x00 : 0xff; + break; +#if LV_COLOR_DEPTH == 16 + case LV_IMG_CF_RGB565A8: + a = *(src + src_stride * src_h * sizeof(lv_color_t) + (ys_int * src_stride) + xs_int); + break; +#endif + default: + a = 0xff; + } + + if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { + abuf[x] = (a * (0xFF - xs_fract)) >> 8; + } + else if((ys_int == 0 && y_next < 0) || (ys_int == src_h - 1 && y_next > 0)) { + abuf[x] = (a * (0xFF - ys_fract)) >> 8; + } + else { + abuf[x] = 0x00; + } + } + } +} + +static void transform_point_upscaled(point_transform_dsc_t * t, int32_t xin, int32_t yin, int32_t * xout, + int32_t * yout) +{ + if(t->angle == 0 && t->zoom == LV_IMG_ZOOM_NONE) { + *xout = xin * 256; + *yout = yin * 256; + return; + } + + xin -= t->pivot.x; + yin -= t->pivot.y; + + if(t->angle == 0) { + *xout = ((int32_t)(xin * t->zoom)) + (t->pivot_x_256); + *yout = ((int32_t)(yin * t->zoom)) + (t->pivot_y_256); + } + else if(t->zoom == LV_IMG_ZOOM_NONE) { + *xout = ((t->cosma * xin - t->sinma * yin) >> 2) + (t->pivot_x_256); + *yout = ((t->sinma * xin + t->cosma * yin) >> 2) + (t->pivot_y_256); + } + else { + *xout = (((t->cosma * xin - t->sinma * yin) * t->zoom) >> 10) + (t->pivot_x_256); + *yout = (((t->sinma * xin + t->cosma * yin) * t->zoom) >> 10) + (t->pivot_y_256); + } +} + +#endif + diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk new file mode 100644 index 000000000..bc19e3802 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk @@ -0,0 +1,6 @@ +CSRCS += lv_gpu_swm341_dma2d.c + +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d + +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c new file mode 100644 index 000000000..74a539467 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c @@ -0,0 +1,241 @@ +/** + * @file lv_gpu_swm341_dma2d.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_gpu_swm341_dma2d.h" +#include "../../core/lv_refr.h" + +#if LV_USE_GPU_SWM341_DMA2D + +#include LV_GPU_SWM341_DMA2D_INCLUDE + +/********************* + * DEFINES + *********************/ + +#if LV_COLOR_16_SWAP + #error "Can't use DMA2D with LV_COLOR_16_SWAP 1" +#endif + +#if LV_COLOR_DEPTH == 8 + #error "Can't use DMA2D with LV_COLOR_DEPTH == 8" +#endif + +#if LV_COLOR_DEPTH == 16 + #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_RGB565 +#elif LV_COLOR_DEPTH == 32 + #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_ARGB8888 +#else + /*Can't use GPU with other formats*/ +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, + lv_color_t color); + +static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa); + +static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Turn on the peripheral and set output color mode, this only needs to be done once + */ +void lv_draw_swm341_dma2d_init(void) +{ + /*Enable DMA2D clock*/ + SYS->CLKEN0 |= (1 << SYS_CLKEN0_DMA2D_Pos); + + DMA2D->CR &= ~DMA2D_CR_WAIT_Msk; + DMA2D->CR |= (CyclesPerUs << DMA2D_CR_WAIT_Pos); + + DMA2D->IF = 0xFF; + DMA2D->IE = (0 << DMA2D_IE_DONE_Pos); + + /*set output colour mode*/ + DMA2D->L[DMA2D_LAYER_OUT].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); +} + +void lv_draw_swm341_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + + lv_draw_sw_init_ctx(drv, draw_ctx); + + lv_draw_swm341_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; + + dma2d_draw_ctx->blend = lv_draw_swm341_dma2d_blend; + // dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_swm341_dma2d_img_decoded; + dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_swm341_dma2d_wait_cb; +} + +void lv_draw_swm341_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ + LV_UNUSED(drv); + LV_UNUSED(draw_ctx); +} + +void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) +{ + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) + return; + + bool done = false; + + if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); + + lv_color_t * dest_buf = draw_ctx->buf; + dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); + + const lv_color_t * src_buf = dsc->src_buf; + if(src_buf) { + lv_draw_sw_blend_basic(draw_ctx, dsc); + lv_coord_t src_stride; + src_stride = lv_area_get_width(dsc->blend_area); + src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1); + lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_draw_swm341_dma2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa); + done = true; + } + else if(dsc->opa >= LV_OPA_MAX) { + lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_draw_swm341_dma2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color); + done = true; + } + } + + if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc); +} + +static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) +{ + /*TODO basic ARGB8888 image can be handles here*/ + + lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format); +} + +static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, + lv_color_t color) +{ + /*Simply fill an area*/ + int32_t area_w = lv_area_get_width(fill_area); + int32_t area_h = lv_area_get_height(fill_area); + +#if 1 + DMA2D->L[DMA2D_LAYER_OUT].COLOR = color.full; + + DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; + DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - area_w; + DMA2D->NLR = ((area_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((area_h - 1) << DMA2D_NLR_NLINE_Pos); + + /*start transfer*/ + DMA2D->CR &= ~DMA2D_CR_MODE_Msk; + DMA2D->CR |= (3 << DMA2D_CR_MODE_Pos) | + (1 << DMA2D_CR_START_Pos); +#else + for(uint32_t y = 0; y < area_h; y++) { + for(uint32_t x = 0; x < area_w; x++) { + dest_buf[y * dest_stride + x] = color; + } + } +#endif +} + +static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa) +{ + + /*Simple copy*/ + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + + if(opa >= LV_OPA_MAX) { +#if 1 + /*copy output colour mode, this register controls both input and output colour format*/ + DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf; + DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w; + DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); + + DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; + DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w; + + DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos); + + /*start transfer*/ + DMA2D->CR &= ~DMA2D_CR_MODE_Msk; + DMA2D->CR |= (0 << DMA2D_CR_MODE_Pos) | + (1 << DMA2D_CR_START_Pos); +#else + lv_color_t temp_buf[1024]; + for(uint32_t y = 0; y < dest_h; y++) { + memcpy(temp_buf, &src_buf[y * src_stride], dest_w * sizeof(lv_color_t)); + memcpy(&dest_buf[y * dest_stride], temp_buf, dest_w * sizeof(lv_color_t)); + } +#endif + } + else { + DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf; + DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w; + DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos) + /*alpha mode 2, replace with foreground * alpha value*/ + | (2 << DAM2D_PFCCR_AMODE_Pos) + /*alpha value*/ + | (opa << DMA2D_PFCCR_ALPHA_Pos); + + DMA2D->L[DMA2D_LAYER_BG].MAR = (uint32_t)dest_buf; + DMA2D->L[DMA2D_LAYER_BG].OR = dest_stride - dest_w; + DMA2D->L[DMA2D_LAYER_BG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); + + DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; + DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w; + + DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos); + + /*start transfer*/ + DMA2D->CR &= ~DMA2D_CR_MODE_Msk; + DMA2D->CR |= (2 << DMA2D_CR_MODE_Pos) | + (1 << DMA2D_CR_START_Pos); + } +} + +void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx) +{ + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + if(disp->driver && disp->driver->wait_cb) { + while(DMA2D->CR & DMA2D_CR_START_Msk) { + disp->driver->wait_cb(disp->driver); + } + } + else { + while(DMA2D->CR & DMA2D_CR_START_Msk); + } + lv_draw_sw_wait_for_finish(draw_ctx); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h new file mode 100644 index 000000000..20b892260 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h @@ -0,0 +1,64 @@ +/** + * @file lv_gpu_swm341_dma2d.h + * + */ + +#ifndef LV_GPU_SWM341_DMA2D_H +#define LV_GPU_SWM341_DMA2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../hal/lv_hal_disp.h" +#include "../sw/lv_draw_sw.h" + +#if LV_USE_GPU_SWM341_DMA2D + +/********************* + * DEFINES + *********************/ + +#define LV_SWM341_DMA2D_ARGB8888 0 +#define LV_SWM341_DMA2D_RGB888 1 +#define LV_SWM341_DMA2D_RGB565 2 + +/********************** + * TYPEDEFS + **********************/ +typedef lv_draw_sw_ctx_t lv_draw_swm341_dma2d_ctx_t; + +struct _lv_disp_drv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Turn on the peripheral and set output color mode, this only needs to be done once + */ +void lv_draw_swm341_dma2d_init(void); + +void lv_draw_swm341_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_swm341_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + +void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SWM341_DMA2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_SWM341_DMA2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/README.md b/lib/libesp32_lvgl/lvgl/src/extra/README.md index 11742114d..80bb49d4f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/README.md +++ b/lib/libesp32_lvgl/lvgl/src/extra/README.md @@ -1,6 +1,6 @@ # Extra components -This directory contains extra (optional) components to lvgl. +This directory contains extra (optional) components to lvgl. It's a good place for contributions as there are less strict expectations about the completeness and flexibility of the components here. In other words, if you have created a complex widget from other widgets, or modified an existing widget with special events, styles or animations, or have a new feature that could work as a plugin to lvgl feel free to the share it here. @@ -10,13 +10,13 @@ In other words, if you have created a complex widget from other widgets, or modi - Please and follow the [Coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) of LVGL - Add setter/getter functions in pair - Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h) -- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs) +- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs) - Add [examples](https://github.com/lvgl/lvgl/tree/master/examples) - Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md) - Add yourself to the [Contributors](#contributors) section below. ## Ideas -Here some ideas as inspiration feel free to contribute with ideas too. +Here some ideas as inspiration feel free to contribute with ideas too. - New [Calendar headers](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/calendar) - Color picker with RGB and or HSV bars - Ruler, horizontal or vertical with major and minor ticks and labels @@ -27,5 +27,5 @@ Here some ideas as inspiration feel free to contribute with ideas too. ## Contributors - lv_animimg: @ZhaoQiang-b45475 -- lv_span: @guoweilkd +- lv_span: @guoweilkd - lv_menu: @HX2003 \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c index 118034273..405a56b7f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c @@ -65,7 +65,7 @@ static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id); /********************** * GLOBAL VARIABLES **********************/ -uint32_t LV_LAYOUT_FLEX; +uint16_t LV_LAYOUT_FLEX; lv_style_prop_t LV_STYLE_FLEX_FLOW; lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; @@ -93,10 +93,10 @@ void lv_flex_init(void) { LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL); - LV_STYLE_FLEX_FLOW = lv_style_register_prop(); - LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; + LV_STYLE_FLEX_FLOW = lv_style_register_prop(LV_STYLE_PROP_FLAG_NONE); + LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); } void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) @@ -428,6 +428,7 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i for(i = 0; i < t->grow_item_cnt; i++) { if(t->grow_dsc[i].clamped == 0) { + LV_ASSERT(grow_value_sum != 0); grow_unit = grow_max_size / grow_value_sum; lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value; lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size); @@ -525,7 +526,7 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i item->coords.y1 += diff_y; item->coords.y2 += diff_y; lv_obj_invalidate(item); - lv_obj_move_children_by(item, diff_x, diff_y, true); + lv_obj_move_children_by(item, diff_x, diff_y, false); } if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h index 139fd4810..1499d884f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h @@ -57,7 +57,7 @@ typedef enum { /********************** * GLOBAL VARIABLES **********************/ -extern uint32_t LV_LAYOUT_FLEX; +extern uint16_t LV_LAYOUT_FLEX; extern lv_style_prop_t LV_STYLE_FLEX_FLOW; extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c index 6812a04a2..74f8e95fb 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c @@ -102,7 +102,7 @@ static inline uint8_t get_grid_row_align(lv_obj_t * obj) /********************** * GLOBAL VARIABLES **********************/ -uint32_t LV_LAYOUT_GRID; +uint16_t LV_LAYOUT_GRID; lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; @@ -131,17 +131,17 @@ void lv_grid_init(void) { LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL); - LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; + LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; - LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR; + LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); } void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) @@ -561,6 +561,8 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) if(IS_FR(x)) { lv_coord_t f = GET_FR(x); c->h[i] = (free_h * f) / row_fr_cnt; + last_fr_i = i; + last_fr_x = f; } } @@ -685,7 +687,7 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * item->coords.y1 += diff_y; item->coords.y2 += diff_y; lv_obj_invalidate(item); - lv_obj_move_children_by(item, diff_x, diff_y, true); + lv_obj_move_children_by(item, diff_x, diff_y, false); } } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h index cd2510ec0..5c4f76725 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h @@ -53,7 +53,7 @@ typedef enum { * GLOBAL VARIABLES **********************/ -extern uint32_t LV_LAYOUT_GRID; +extern uint16_t LV_LAYOUT_GRID; extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c new file mode 100644 index 000000000..f89a0a8c7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c @@ -0,0 +1,258 @@ +/** + * @file lv_bmp.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_BMP + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_fs_file_t f; + unsigned int px_offset; + int px_width; + int px_height; + unsigned int bpp; + int row_size_bytes; +} bmp_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); +static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); + + +static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, + lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf); + +static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_bmp_init(void) +{ + lv_img_decoder_t * dec = lv_img_decoder_create(); + lv_img_decoder_set_info_cb(dec, decoder_info); + lv_img_decoder_set_open_cb(dec, decoder_open); + lv_img_decoder_set_read_line_cb(dec, decoder_read_line); + lv_img_decoder_set_close_cb(dec, decoder_close); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Get info about a PNG image + * @param src can be file name or pointer to a C array + * @param header store the info here + * @return LV_RES_OK: no error; LV_RES_INV: can't get the info + */ +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) +{ + LV_UNUSED(decoder); + + lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/ + + /*If it's a BMP file...*/ + if(src_type == LV_IMG_SRC_FILE) { + const char * fn = src; + if(strcmp(lv_fs_get_ext(fn), "bmp") == 0) { /*Check the extension*/ + /*Save the data in the header*/ + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return LV_RES_INV; + uint8_t headers[54]; + + lv_fs_read(&f, headers, 54, NULL); + uint32_t w; + uint32_t h; + memcpy(&w, headers + 18, 4); + memcpy(&h, headers + 22, 4); + header->w = w; + header->h = h; + header->always_zero = 0; + lv_fs_close(&f); +#if LV_COLOR_DEPTH == 32 + uint16_t bpp; + memcpy(&bpp, headers + 28, 2); + header->cf = bpp == 32 ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; +#else + header->cf = LV_IMG_CF_TRUE_COLOR; +#endif + return LV_RES_OK; + } + } + /* BMP file as data not supported for simplicity. + * Convert them to LVGL compatible C arrays directly. */ + else if(src_type == LV_IMG_SRC_VARIABLE) { + return LV_RES_INV; + } + + return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/ +} + + +/** + * Open a PNG image and return the decided image + * @param src can be file name or pointer to a C array + * @param style style of the image object (unused now but certain formats might use it) + * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed + */ +static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + + /*If it's a PNG file...*/ + if(dsc->src_type == LV_IMG_SRC_FILE) { + const char * fn = dsc->src; + + if(strcmp(lv_fs_get_ext(fn), "bmp") != 0) { + return LV_RES_INV; /*Check the extension*/ + } + + bmp_dsc_t b; + memset(&b, 0x00, sizeof(b)); + + lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD); + if(res == LV_RES_OK) return LV_RES_INV; + + uint8_t header[54]; + lv_fs_read(&b.f, header, 54, NULL); + + if(0x42 != header[0] || 0x4d != header[1]) { + lv_fs_close(&b.f); + return LV_RES_INV; + } + + memcpy(&b.px_offset, header + 10, 4); + memcpy(&b.px_width, header + 18, 4); + memcpy(&b.px_height, header + 22, 4); + memcpy(&b.bpp, header + 28, 2); + b.row_size_bytes = ((b.bpp * b.px_width + 31) / 32) * 4; + + bool color_depth_error = false; + if(LV_COLOR_DEPTH == 32 && (b.bpp != 32 && b.bpp != 24)) { + LV_LOG_WARN("LV_COLOR_DEPTH == 32 but bpp is %d (should be 32 or 24)", b.bpp); + color_depth_error = true; + } + else if(LV_COLOR_DEPTH == 16 && b.bpp != 16) { + LV_LOG_WARN("LV_COLOR_DEPTH == 16 but bpp is %d (should be 16)", b.bpp); + color_depth_error = true; + } + else if(LV_COLOR_DEPTH == 8 && b.bpp != 8) { + LV_LOG_WARN("LV_COLOR_DEPTH == 8 but bpp is %d (should be 8)", b.bpp); + color_depth_error = true; + } + + if(color_depth_error) { + dsc->error_msg = "Color depth mismatch"; + lv_fs_close(&b.f); + return LV_RES_INV; + } + + dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t)); + LV_ASSERT_MALLOC(dsc->user_data); + if(dsc->user_data == NULL) return LV_RES_INV; + memcpy(dsc->user_data, &b, sizeof(b)); + + dsc->img_data = NULL; + return LV_RES_OK; + } + /* BMP file as data not supported for simplicity. + * Convert them to LVGL compatible C arrays directly. */ + else if(dsc->src_type == LV_IMG_SRC_VARIABLE) { + return LV_RES_INV; + } + + return LV_RES_INV; /*If not returned earlier then it failed*/ +} + + +static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, + lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) +{ + LV_UNUSED(decoder); + + bmp_dsc_t * b = dsc->user_data; + y = (b->px_height - 1) - y; /*BMP images are stored upside down*/ + uint32_t p = b->px_offset + b->row_size_bytes * y; + p += x * (b->bpp / 8); + lv_fs_seek(&b->f, p, LV_FS_SEEK_SET); + lv_fs_read(&b->f, buf, len * (b->bpp / 8), NULL); + +#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 1 + for(unsigned int i = 0; i < len * (b->bpp / 8); i += 2) { + buf[i] = buf[i] ^ buf[i + 1]; + buf[i + 1] = buf[i] ^ buf[i + 1]; + buf[i] = buf[i] ^ buf[i + 1]; + } + +#elif LV_COLOR_DEPTH == 32 + if(b->bpp == 32) { + lv_coord_t i; + for(i = 0; i < len; i++) { + uint8_t b0 = buf[i * 4]; + uint8_t b1 = buf[i * 4 + 1]; + uint8_t b2 = buf[i * 4 + 2]; + uint8_t b3 = buf[i * 4 + 3]; + lv_color32_t * c = (lv_color32_t *)&buf[i * 4]; + c->ch.red = b2; + c->ch.green = b1; + c->ch.blue = b0; + c->ch.alpha = b3; + } + } + if(b->bpp == 24) { + lv_coord_t i; + + for(i = len - 1; i >= 0; i--) { + uint8_t * t = &buf[i * 3]; + lv_color32_t * c = (lv_color32_t *)&buf[i * 4]; + c->ch.red = t[2]; + c->ch.green = t[1]; + c->ch.blue = t[0]; + c->ch.alpha = 0xff; + } + } +#endif + + return LV_RES_OK; +} + + +/** + * Free the allocated resources + */ +static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + bmp_dsc_t * b = dsc->user_data; + lv_fs_close(&b->f); + lv_mem_free(dsc->user_data); + +} + +#endif /*LV_USE_BMP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h new file mode 100644 index 000000000..db1e54096 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h @@ -0,0 +1,42 @@ +/** + * @file lv_bmp.h + * + */ + +#ifndef LV_BMP_H +#define LV_BMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_BMP + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_bmp_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BMP*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BMP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c new file mode 100644 index 000000000..efaa6925e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c @@ -0,0 +1,875 @@ +/** + * @file lv_ffmpeg.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_ffmpeg.h" +#if LV_USE_FFMPEG != 0 + +#include +#include +#include +#include +#include +#include + +/********************* + * DEFINES + *********************/ +#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 + #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB8 +#elif LV_COLOR_DEPTH == 16 + #if LV_COLOR_16_SWAP == 0 + #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565LE + #else + #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565BE + #endif +#elif LV_COLOR_DEPTH == 32 + #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_BGR0 +#else + #error Unsupported LV_COLOR_DEPTH +#endif + +#define MY_CLASS &lv_ffmpeg_player_class + +#define FRAME_DEF_REFR_PERIOD 33 /*[ms]*/ + +/********************** + * TYPEDEFS + **********************/ +struct ffmpeg_context_s { + AVFormatContext * fmt_ctx; + AVCodecContext * video_dec_ctx; + AVStream * video_stream; + uint8_t * video_src_data[4]; + uint8_t * video_dst_data[4]; + struct SwsContext * sws_ctx; + AVFrame * frame; + AVPacket pkt; + int video_stream_idx; + int video_src_linesize[4]; + int video_dst_linesize[4]; + enum AVPixelFormat video_dst_pix_fmt; + bool has_alpha; +}; + +#pragma pack(1) + +struct lv_img_pixel_color_s { + lv_color_t c; + uint8_t alpha; +}; + +#pragma pack() + +/********************** + * STATIC PROTOTYPES + **********************/ + +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); +static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); +static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); + +static struct ffmpeg_context_s * ffmpeg_open_file(const char * path); +static void ffmpeg_close(struct ffmpeg_context_s * ffmpeg_ctx); +static void ffmpeg_close_src_ctx(struct ffmpeg_context_s * ffmpeg_ctx); +static void ffmpeg_close_dst_ctx(struct ffmpeg_context_s * ffmpeg_ctx); +static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx); +static int ffmpeg_get_img_header(const char * path, lv_img_header_t * header); +static int ffmpeg_get_frame_refr_period(struct ffmpeg_context_s * ffmpeg_ctx); +static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx); +static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx); +static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx); +static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt); +static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt); + +static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); + +#if LV_COLOR_DEPTH != 32 + static void convert_color_depth(uint8_t * img, uint32_t px_cnt); +#endif + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_ffmpeg_player_class = { + .constructor_cb = lv_ffmpeg_player_constructor, + .destructor_cb = lv_ffmpeg_player_destructor, + .instance_size = sizeof(lv_ffmpeg_player_t), + .base_class = &lv_img_class +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_ffmpeg_init(void) +{ + lv_img_decoder_t * dec = lv_img_decoder_create(); + lv_img_decoder_set_info_cb(dec, decoder_info); + lv_img_decoder_set_open_cb(dec, decoder_open); + lv_img_decoder_set_close_cb(dec, decoder_close); + +#if LV_FFMPEG_AV_DUMP_FORMAT == 0 + av_log_set_level(AV_LOG_QUIET); +#endif +} + +int lv_ffmpeg_get_frame_num(const char * path) +{ + int ret = -1; + struct ffmpeg_context_s * ffmpeg_ctx = ffmpeg_open_file(path); + + if(ffmpeg_ctx) { + ret = ffmpeg_ctx->video_stream->nb_frames; + ffmpeg_close(ffmpeg_ctx); + } + + return ret; +} + +lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent) +{ + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_res_t res = LV_RES_INV; + + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + + if(player->ffmpeg_ctx) { + ffmpeg_close(player->ffmpeg_ctx); + player->ffmpeg_ctx = NULL; + } + + lv_timer_pause(player->timer); + + player->ffmpeg_ctx = ffmpeg_open_file(path); + + if(!player->ffmpeg_ctx) { + LV_LOG_ERROR("ffmpeg file open failed: %s", path); + goto failed; + } + + if(ffmpeg_image_allocate(player->ffmpeg_ctx) < 0) { + LV_LOG_ERROR("ffmpeg image allocate failed"); + ffmpeg_close(player->ffmpeg_ctx); + goto failed; + } + + bool has_alpha = player->ffmpeg_ctx->has_alpha; + int width = player->ffmpeg_ctx->video_dec_ctx->width; + int height = player->ffmpeg_ctx->video_dec_ctx->height; + uint32_t data_size = 0; + + if(has_alpha) { + data_size = width * height * LV_IMG_PX_SIZE_ALPHA_BYTE; + } + else { + data_size = width * height * LV_COLOR_SIZE / 8; + } + + player->imgdsc.header.always_zero = 0; + player->imgdsc.header.w = width; + player->imgdsc.header.h = height; + player->imgdsc.data_size = data_size; + player->imgdsc.header.cf = has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; + player->imgdsc.data = ffmpeg_get_img_data(player->ffmpeg_ctx); + + lv_img_set_src(&player->img.obj, &(player->imgdsc)); + + int period = ffmpeg_get_frame_refr_period(player->ffmpeg_ctx); + + if(period > 0) { + LV_LOG_INFO("frame refresh period = %d ms, rate = %d fps", + period, 1000 / period); + lv_timer_set_period(player->timer, period); + } + else { + LV_LOG_WARN("unable to get frame refresh period"); + } + + res = LV_RES_OK; + +failed: + return res; +} + +void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + + if(!player->ffmpeg_ctx) { + LV_LOG_ERROR("ffmpeg_ctx is NULL"); + return; + } + + lv_timer_t * timer = player->timer; + + switch(cmd) { + case LV_FFMPEG_PLAYER_CMD_START: + av_seek_frame(player->ffmpeg_ctx->fmt_ctx, + 0, 0, AVSEEK_FLAG_BACKWARD); + lv_timer_resume(timer); + LV_LOG_INFO("ffmpeg player start"); + break; + case LV_FFMPEG_PLAYER_CMD_STOP: + av_seek_frame(player->ffmpeg_ctx->fmt_ctx, + 0, 0, AVSEEK_FLAG_BACKWARD); + lv_timer_pause(timer); + LV_LOG_INFO("ffmpeg player stop"); + break; + case LV_FFMPEG_PLAYER_CMD_PAUSE: + lv_timer_pause(timer); + LV_LOG_INFO("ffmpeg player pause"); + break; + case LV_FFMPEG_PLAYER_CMD_RESUME: + lv_timer_resume(timer); + LV_LOG_INFO("ffmpeg player resume"); + break; + default: + LV_LOG_ERROR("Error cmd: %d", cmd); + break; + } +} + +void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + player->auto_restart = en; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) +{ + /* Get the source type */ + lv_img_src_t src_type = lv_img_src_get_type(src); + + if(src_type == LV_IMG_SRC_FILE) { + const char * fn = src; + + if(ffmpeg_get_img_header(fn, header) < 0) { + LV_LOG_ERROR("ffmpeg can't get image header"); + return LV_RES_INV; + } + + return LV_RES_OK; + } + + /* If didn't succeeded earlier then it's an error */ + return LV_RES_INV; +} + +static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + if(dsc->src_type == LV_IMG_SRC_FILE) { + const char * path = dsc->src; + + struct ffmpeg_context_s * ffmpeg_ctx = ffmpeg_open_file(path); + + if(ffmpeg_ctx == NULL) { + return LV_RES_INV; + } + + if(ffmpeg_image_allocate(ffmpeg_ctx) < 0) { + LV_LOG_ERROR("ffmpeg image allocate failed"); + ffmpeg_close(ffmpeg_ctx); + return LV_RES_INV; + } + + if(ffmpeg_update_next_frame(ffmpeg_ctx) < 0) { + ffmpeg_close(ffmpeg_ctx); + LV_LOG_ERROR("ffmpeg update frame failed"); + return LV_RES_INV; + } + + ffmpeg_close_src_ctx(ffmpeg_ctx); + uint8_t * img_data = ffmpeg_get_img_data(ffmpeg_ctx); + +#if LV_COLOR_DEPTH != 32 + if(ffmpeg_ctx->has_alpha) { + convert_color_depth(img_data, dsc->header.w * dsc->header.h); + } +#endif + + dsc->user_data = ffmpeg_ctx; + dsc->img_data = img_data; + + /* The image is fully decoded. Return with its pointer */ + return LV_RES_OK; + } + + /* If not returned earlier then it failed */ + return LV_RES_INV; +} + +static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + struct ffmpeg_context_s * ffmpeg_ctx = dsc->user_data; + ffmpeg_close(ffmpeg_ctx); +} + +#if LV_COLOR_DEPTH != 32 + +static void convert_color_depth(uint8_t * img, uint32_t px_cnt) +{ + lv_color32_t * img_src_p = (lv_color32_t *)img; + struct lv_img_pixel_color_s * img_dst_p = (struct lv_img_pixel_color_s *)img; + + for(uint32_t i = 0; i < px_cnt; i++) { + lv_color32_t temp = *img_src_p; + img_dst_p->c = lv_color_hex(temp.full); + img_dst_p->alpha = temp.ch.alpha; + + img_src_p++; + img_dst_p++; + } +} + +#endif + +static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx) +{ + uint8_t * img_data = ffmpeg_ctx->video_dst_data[0]; + + if(img_data == NULL) { + LV_LOG_ERROR("ffmpeg video dst data is NULL"); + } + + return img_data; +} + +static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt); + + if(desc == NULL) { + return false; + } + + if(pix_fmt == AV_PIX_FMT_PAL8) { + return true; + } + + return (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? true : false; +} + +static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt); + + if(desc == NULL) { + return false; + } + + return !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components >= 2; +} + +static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx) +{ + int ret = -1; + + int width = ffmpeg_ctx->video_dec_ctx->width; + int height = ffmpeg_ctx->video_dec_ctx->height; + AVFrame * frame = ffmpeg_ctx->frame; + + if(frame->width != width + || frame->height != height + || frame->format != ffmpeg_ctx->video_dec_ctx->pix_fmt) { + + /* To handle this change, one could call av_image_alloc again and + * decode the following frames into another rawvideo file. + */ + LV_LOG_ERROR("Width, height and pixel format have to be " + "constant in a rawvideo file, but the width, height or " + "pixel format of the input video changed:\n" + "old: width = %d, height = %d, format = %s\n" + "new: width = %d, height = %d, format = %s\n", + width, + height, + av_get_pix_fmt_name(ffmpeg_ctx->video_dec_ctx->pix_fmt), + frame->width, frame->height, + av_get_pix_fmt_name(frame->format)); + goto failed; + } + + LV_LOG_TRACE("video_frame coded_n:%d", frame->coded_picture_number); + + /* copy decoded frame to destination buffer: + * this is required since rawvideo expects non aligned data + */ + av_image_copy(ffmpeg_ctx->video_src_data, ffmpeg_ctx->video_src_linesize, + (const uint8_t **)(frame->data), frame->linesize, + ffmpeg_ctx->video_dec_ctx->pix_fmt, width, height); + + if(ffmpeg_ctx->sws_ctx == NULL) { + int swsFlags = SWS_BILINEAR; + + if(ffmpeg_pix_fmt_is_yuv(ffmpeg_ctx->video_dec_ctx->pix_fmt)) { + + /* When the video width and height are not multiples of 8, + * and there is no size change in the conversion, + * a blurry screen will appear on the right side + * This problem was discovered in 2012 and + * continues to exist in version 4.1.3 in 2019 + * This problem can be avoided by increasing SWS_ACCURATE_RND + */ + if((width & 0x7) || (height & 0x7)) { + LV_LOG_WARN("The width(%d) and height(%d) the image " + "is not a multiple of 8, " + "the decoding speed may be reduced", + width, height); + swsFlags |= SWS_ACCURATE_RND; + } + } + + ffmpeg_ctx->sws_ctx = sws_getContext( + width, height, ffmpeg_ctx->video_dec_ctx->pix_fmt, + width, height, ffmpeg_ctx->video_dst_pix_fmt, + swsFlags, + NULL, NULL, NULL); + } + + if(!ffmpeg_ctx->has_alpha) { + int lv_linesize = sizeof(lv_color_t) * width; + int dst_linesize = ffmpeg_ctx->video_dst_linesize[0]; + if(dst_linesize != lv_linesize) { + LV_LOG_WARN("ffmpeg linesize = %d, but lvgl image require %d", + dst_linesize, + lv_linesize); + ffmpeg_ctx->video_dst_linesize[0] = lv_linesize; + } + } + + ret = sws_scale( + ffmpeg_ctx->sws_ctx, + (const uint8_t * const *)(ffmpeg_ctx->video_src_data), + ffmpeg_ctx->video_src_linesize, + 0, + height, + ffmpeg_ctx->video_dst_data, + ffmpeg_ctx->video_dst_linesize); + +failed: + return ret; +} + +static int ffmpeg_decode_packet(AVCodecContext * dec, const AVPacket * pkt, + struct ffmpeg_context_s * ffmpeg_ctx) +{ + int ret = 0; + + /* submit the packet to the decoder */ + ret = avcodec_send_packet(dec, pkt); + if(ret < 0) { + LV_LOG_ERROR("Error submitting a packet for decoding (%s)", + av_err2str(ret)); + return ret; + } + + /* get all the available frames from the decoder */ + while(ret >= 0) { + ret = avcodec_receive_frame(dec, ffmpeg_ctx->frame); + if(ret < 0) { + + /* those two return values are special and mean there is + * no output frame available, + * but there were no errors during decoding + */ + if(ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + return 0; + } + + LV_LOG_ERROR("Error during decoding (%s)", av_err2str(ret)); + return ret; + } + + /* write the frame data to output file */ + if(dec->codec->type == AVMEDIA_TYPE_VIDEO) { + ret = ffmpeg_output_video_frame(ffmpeg_ctx); + } + + av_frame_unref(ffmpeg_ctx->frame); + if(ret < 0) { + LV_LOG_WARN("ffmpeg_decode_packet ended %d", ret); + return ret; + } + } + + return 0; +} + +static int ffmpeg_open_codec_context(int * stream_idx, + AVCodecContext ** dec_ctx, AVFormatContext * fmt_ctx, + enum AVMediaType type) +{ + int ret; + int stream_index; + AVStream * st; + AVCodec * dec = NULL; + AVDictionary * opts = NULL; + + ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); + if(ret < 0) { + LV_LOG_ERROR("Could not find %s stream in input file", + av_get_media_type_string(type)); + return ret; + } + else { + stream_index = ret; + st = fmt_ctx->streams[stream_index]; + + /* find decoder for the stream */ + dec = avcodec_find_decoder(st->codecpar->codec_id); + if(dec == NULL) { + LV_LOG_ERROR("Failed to find %s codec", + av_get_media_type_string(type)); + return AVERROR(EINVAL); + } + + /* Allocate a codec context for the decoder */ + *dec_ctx = avcodec_alloc_context3(dec); + if(*dec_ctx == NULL) { + LV_LOG_ERROR("Failed to allocate the %s codec context", + av_get_media_type_string(type)); + return AVERROR(ENOMEM); + } + + /* Copy codec parameters from input stream to output codec context */ + if((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) { + LV_LOG_ERROR( + "Failed to copy %s codec parameters to decoder context", + av_get_media_type_string(type)); + return ret; + } + + /* Init the decoders */ + if((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) { + LV_LOG_ERROR("Failed to open %s codec", + av_get_media_type_string(type)); + return ret; + } + + *stream_idx = stream_index; + } + + return 0; +} + +static int ffmpeg_get_img_header(const char * filepath, + lv_img_header_t * header) +{ + int ret = -1; + + AVFormatContext * fmt_ctx = NULL; + AVCodecContext * video_dec_ctx = NULL; + int video_stream_idx; + + /* open input file, and allocate format context */ + if(avformat_open_input(&fmt_ctx, filepath, NULL, NULL) < 0) { + LV_LOG_ERROR("Could not open source file %s", filepath); + goto failed; + } + + /* retrieve stream information */ + if(avformat_find_stream_info(fmt_ctx, NULL) < 0) { + LV_LOG_ERROR("Could not find stream information"); + goto failed; + } + + if(ffmpeg_open_codec_context(&video_stream_idx, &video_dec_ctx, + fmt_ctx, AVMEDIA_TYPE_VIDEO) + >= 0) { + bool has_alpha = ffmpeg_pix_fmt_has_alpha(video_dec_ctx->pix_fmt); + + /* allocate image where the decoded image will be put */ + header->w = video_dec_ctx->width; + header->h = video_dec_ctx->height; + header->always_zero = 0; + header->cf = (has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR); + + ret = 0; + } + +failed: + avcodec_free_context(&video_dec_ctx); + avformat_close_input(&fmt_ctx); + + return ret; +} + +static int ffmpeg_get_frame_refr_period(struct ffmpeg_context_s * ffmpeg_ctx) +{ + int avg_frame_rate_num = ffmpeg_ctx->video_stream->avg_frame_rate.num; + if(avg_frame_rate_num > 0) { + int period = 1000 * (int64_t)ffmpeg_ctx->video_stream->avg_frame_rate.den + / avg_frame_rate_num; + return period; + } + + return -1; +} + +static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx) +{ + int ret = 0; + + while(1) { + + /* read frames from the file */ + if(av_read_frame(ffmpeg_ctx->fmt_ctx, &(ffmpeg_ctx->pkt)) >= 0) { + bool is_image = false; + + /* check if the packet belongs to a stream we are interested in, + * otherwise skip it + */ + if(ffmpeg_ctx->pkt.stream_index == ffmpeg_ctx->video_stream_idx) { + ret = ffmpeg_decode_packet(ffmpeg_ctx->video_dec_ctx, + &(ffmpeg_ctx->pkt), ffmpeg_ctx); + is_image = true; + } + + av_packet_unref(&(ffmpeg_ctx->pkt)); + + if(ret < 0) { + LV_LOG_WARN("video frame is empty %d", ret); + break; + } + + /* Used to filter data that is not an image */ + if(is_image) { + break; + } + } + else { + ret = -1; + break; + } + } + + return ret; +} + +struct ffmpeg_context_s * ffmpeg_open_file(const char * path) +{ + if(path == NULL || strlen(path) == 0) { + LV_LOG_ERROR("file path is empty"); + return NULL; + } + + struct ffmpeg_context_s * ffmpeg_ctx = calloc(1, sizeof(struct ffmpeg_context_s)); + + if(ffmpeg_ctx == NULL) { + LV_LOG_ERROR("ffmpeg_ctx malloc failed"); + goto failed; + } + + /* open input file, and allocate format context */ + + if(avformat_open_input(&(ffmpeg_ctx->fmt_ctx), path, NULL, NULL) < 0) { + LV_LOG_ERROR("Could not open source file %s", path); + goto failed; + } + + /* retrieve stream information */ + + if(avformat_find_stream_info(ffmpeg_ctx->fmt_ctx, NULL) < 0) { + LV_LOG_ERROR("Could not find stream information"); + goto failed; + } + + if(ffmpeg_open_codec_context( + &(ffmpeg_ctx->video_stream_idx), + &(ffmpeg_ctx->video_dec_ctx), + ffmpeg_ctx->fmt_ctx, AVMEDIA_TYPE_VIDEO) + >= 0) { + ffmpeg_ctx->video_stream = ffmpeg_ctx->fmt_ctx->streams[ffmpeg_ctx->video_stream_idx]; + + ffmpeg_ctx->has_alpha = ffmpeg_pix_fmt_has_alpha(ffmpeg_ctx->video_dec_ctx->pix_fmt); + + ffmpeg_ctx->video_dst_pix_fmt = (ffmpeg_ctx->has_alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_TRUE_COLOR); + } + +#if LV_FFMPEG_AV_DUMP_FORMAT != 0 + /* dump input information to stderr */ + av_dump_format(ffmpeg_ctx->fmt_ctx, 0, path, 0); +#endif + + if(ffmpeg_ctx->video_stream == NULL) { + LV_LOG_ERROR("Could not find video stream in the input, aborting"); + goto failed; + } + + return ffmpeg_ctx; + +failed: + ffmpeg_close(ffmpeg_ctx); + return NULL; +} + +static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx) +{ + int ret; + + /* allocate image where the decoded image will be put */ + ret = av_image_alloc( + ffmpeg_ctx->video_src_data, + ffmpeg_ctx->video_src_linesize, + ffmpeg_ctx->video_dec_ctx->width, + ffmpeg_ctx->video_dec_ctx->height, + ffmpeg_ctx->video_dec_ctx->pix_fmt, + 4); + + if(ret < 0) { + LV_LOG_ERROR("Could not allocate src raw video buffer"); + return ret; + } + + LV_LOG_INFO("alloc video_src_bufsize = %d", ret); + + ret = av_image_alloc( + ffmpeg_ctx->video_dst_data, + ffmpeg_ctx->video_dst_linesize, + ffmpeg_ctx->video_dec_ctx->width, + ffmpeg_ctx->video_dec_ctx->height, + ffmpeg_ctx->video_dst_pix_fmt, + 4); + + if(ret < 0) { + LV_LOG_ERROR("Could not allocate dst raw video buffer"); + return ret; + } + + LV_LOG_INFO("allocate video_dst_bufsize = %d", ret); + + ffmpeg_ctx->frame = av_frame_alloc(); + + if(ffmpeg_ctx->frame == NULL) { + LV_LOG_ERROR("Could not allocate frame"); + return -1; + } + + /* initialize packet, set data to NULL, let the demuxer fill it */ + av_init_packet(&ffmpeg_ctx->pkt); + ffmpeg_ctx->pkt.data = NULL; + ffmpeg_ctx->pkt.size = 0; + + return 0; +} + +static void ffmpeg_close_src_ctx(struct ffmpeg_context_s * ffmpeg_ctx) +{ + avcodec_free_context(&(ffmpeg_ctx->video_dec_ctx)); + avformat_close_input(&(ffmpeg_ctx->fmt_ctx)); + av_frame_free(&(ffmpeg_ctx->frame)); + if(ffmpeg_ctx->video_src_data[0] != NULL) { + av_free(ffmpeg_ctx->video_src_data[0]); + ffmpeg_ctx->video_src_data[0] = NULL; + } +} + +static void ffmpeg_close_dst_ctx(struct ffmpeg_context_s * ffmpeg_ctx) +{ + if(ffmpeg_ctx->video_dst_data[0] != NULL) { + av_free(ffmpeg_ctx->video_dst_data[0]); + ffmpeg_ctx->video_dst_data[0] = NULL; + } +} + +static void ffmpeg_close(struct ffmpeg_context_s * ffmpeg_ctx) +{ + if(ffmpeg_ctx == NULL) { + LV_LOG_WARN("ffmpeg_ctx is NULL"); + return; + } + + sws_freeContext(ffmpeg_ctx->sws_ctx); + ffmpeg_close_src_ctx(ffmpeg_ctx); + ffmpeg_close_dst_ctx(ffmpeg_ctx); + free(ffmpeg_ctx); + + LV_LOG_INFO("ffmpeg_ctx closed"); +} + +static void lv_ffmpeg_player_frame_update_cb(lv_timer_t * timer) +{ + lv_obj_t * obj = (lv_obj_t *)timer->user_data; + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + + if(!player->ffmpeg_ctx) { + return; + } + + int has_next = ffmpeg_update_next_frame(player->ffmpeg_ctx); + + if(has_next < 0) { + lv_ffmpeg_player_set_cmd(obj, player->auto_restart ? LV_FFMPEG_PLAYER_CMD_START : LV_FFMPEG_PLAYER_CMD_STOP); + return; + } + +#if LV_COLOR_DEPTH != 32 + if(player->ffmpeg_ctx->has_alpha) { + convert_color_depth((uint8_t *)(player->imgdsc.data), + player->imgdsc.header.w * player->imgdsc.header.h); + } +#endif + + lv_img_cache_invalidate_src(lv_img_get_src(obj)); + lv_obj_invalidate(obj); +} + +static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, + lv_obj_t * obj) +{ + LV_TRACE_OBJ_CREATE("begin"); + + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + + player->auto_restart = false; + player->ffmpeg_ctx = NULL; + player->timer = lv_timer_create(lv_ffmpeg_player_frame_update_cb, + FRAME_DEF_REFR_PERIOD, obj); + lv_timer_pause(player->timer); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, + lv_obj_t * obj) +{ + LV_TRACE_OBJ_CREATE("begin"); + + lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; + + if(player->timer) { + lv_timer_del(player->timer); + player->timer = NULL; + } + + lv_img_cache_invalidate_src(lv_img_get_src(obj)); + + ffmpeg_close(player->ffmpeg_ctx); + player->ffmpeg_ctx = NULL; + + LV_TRACE_OBJ_CREATE("finished"); +} + +#endif /*LV_USE_FFMPEG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h new file mode 100644 index 000000000..8c7fc26b1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h @@ -0,0 +1,104 @@ +/** + * @file lv_ffmpeg.h + * + */ +#ifndef LV_FFMPEG_H +#define LV_FFMPEG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FFMPEG != 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct ffmpeg_context_s; + +extern const lv_obj_class_t lv_ffmpeg_player_class; + +typedef struct { + lv_img_t img; + lv_timer_t * timer; + lv_img_dsc_t imgdsc; + bool auto_restart; + struct ffmpeg_context_s * ffmpeg_ctx; +} lv_ffmpeg_player_t; + +typedef enum { + LV_FFMPEG_PLAYER_CMD_START, + LV_FFMPEG_PLAYER_CMD_STOP, + LV_FFMPEG_PLAYER_CMD_PAUSE, + LV_FFMPEG_PLAYER_CMD_RESUME, + _LV_FFMPEG_PLAYER_CMD_LAST +} lv_ffmpeg_player_cmd_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Register FFMPEG image decoder + */ +void lv_ffmpeg_init(void); + +/** + * Get the number of frames contained in the file + * @param path image or video file name + * @return Number of frames, less than 0 means failed + */ +int lv_ffmpeg_get_frame_num(const char * path); + +/** + * Create ffmpeg_player object + * @param parent pointer to an object, it will be the parent of the new player + * @return pointer to the created ffmpeg_player + */ +lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent); + +/** + * Set the path of the file to be played + * @param obj pointer to a ffmpeg_player object + * @param path video file path + * @return LV_RES_OK: no error; LV_RES_INV: can't get the info. + */ +lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path); + +/** + * Set command control video player + * @param obj pointer to a ffmpeg_player object + * @param cmd control commands + */ +void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd); + +/** + * Set the video to automatically replay + * @param obj pointer to a ffmpeg_player object + * @param en true: enable the auto restart + */ +void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FFMPEG*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FFMPEG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c index 73596ece7..cc1d2e6d6 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c @@ -161,8 +161,8 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ * @param drv pointer to a driver where this function belongs * @param file_p pointer to a FIL variable * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c index fb5fcd306..f988daeeb 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c @@ -110,7 +110,7 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; - sprintf(buf, LV_FS_POSIX_PATH "%s", path); + lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s", path); int f = open(buf, flags); if(f < 0) return NULL; @@ -154,8 +154,8 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ * @param drv pointer to a driver where this function belongs * @param file_p a file handle variable * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -176,8 +176,8 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) { LV_UNUSED(drv); - lseek((lv_uintptr_t)file_p, pos, whence); - return LV_FS_RES_OK; + off_t offset = lseek((lv_uintptr_t)file_p, pos, whence); + return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK; } /** @@ -191,8 +191,9 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) { LV_UNUSED(drv); - *pos_p = lseek((lv_uintptr_t)file_p, 0, SEEK_CUR); - return LV_FS_RES_OK; + off_t offset = lseek((lv_uintptr_t)file_p, 0, SEEK_CUR); + *pos_p = offset; + return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK; } #ifdef WIN32 @@ -212,7 +213,7 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) #ifndef WIN32 /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; - sprintf(buf, LV_FS_POSIX_PATH "%s", path); + lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s", path); return opendir(buf); #else HANDLE d = INVALID_HANDLE_VALUE; @@ -220,7 +221,7 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; - sprintf(buf, LV_FS_POSIX_PATH "%s\\*", path); + lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s\\*", path); strcpy(next_fn, ""); d = FindFirstFile(buf, &fdata); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c index e4bf07783..c2de6880e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c @@ -21,10 +21,19 @@ /********************* * DEFINES *********************/ +#define MAX_PATH_LEN 256 /********************** * TYPEDEFS **********************/ +typedef struct { +#ifdef WIN32 + HANDLE dir_p; + char next_fn[MAX_PATH_LEN]; +#else + DIR * dir_p; +#endif +} dir_handle_t; /********************** * STATIC PROTOTYPES @@ -105,8 +114,8 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) /*Make the path relative to the current directory (the projects root folder)*/ - char buf[256]; - sprintf(buf, LV_FS_STDIO_PATH "%s", path); + char buf[MAX_PATH_LEN]; + lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path); return fopen(buf, flags); } @@ -147,8 +156,8 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ * @param drv pointer to a driver where this function belongs * @param file_p pointer to a FILE variable * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -188,10 +197,6 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) return LV_FS_RES_OK; } -#ifdef WIN32 - static char next_fn[256]; -#endif - /** * Initialize a 'DIR' or 'HANDLE' variable for directory reading * @param drv pointer to a driver where this function belongs @@ -201,37 +206,47 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); + dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t)); #ifndef WIN32 /*Make the path relative to the current directory (the projects root folder)*/ - char buf[256]; - sprintf(buf, LV_FS_STDIO_PATH "%s", path); - return opendir(buf); + char buf[MAX_PATH_LEN]; + lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path); + handle->dir_p = opendir(buf); + if(handle->dir_p == NULL) { + lv_mem_free(handle); + return NULL; + } + return handle; #else - HANDLE d = INVALID_HANDLE_VALUE; - WIN32_FIND_DATA fdata; + handle->dir_p = INVALID_HANDLE_VALUE; + WIN32_FIND_DATAA fdata; /*Make the path relative to the current directory (the projects root folder)*/ - char buf[256]; - sprintf(buf, LV_FS_STDIO_PATH "%s\\*", path); + char buf[MAX_PATH_LEN]; + lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s\\*", path); - strcpy(next_fn, ""); - d = FindFirstFile(buf, &fdata); + strcpy(handle->next_fn, ""); + handle->dir_p = FindFirstFileA(buf, &fdata); do { if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { continue; } else { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); } else { - sprintf(next_fn, "%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); } break; } - } while(FindNextFileA(d, &fdata)); + } while(FindNextFileA(handle->dir_p, &fdata)); - return d; + if(handle->dir_p == INVALID_HANDLE_VALUE) { + lv_mem_free(handle); + return INVALID_HANDLE_VALUE; + } + return handle; #endif } @@ -246,13 +261,13 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) { LV_UNUSED(drv); - + dir_handle_t * handle = (dir_handle_t *)dir_p; #ifndef WIN32 struct dirent * entry; do { - entry = readdir(dir_p); + entry = readdir(handle->dir_p); if(entry) { - if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); + if(entry->d_type == DT_DIR) lv_snprintf(fn, MAX_PATH_LEN, "/%s", entry->d_name); else strcpy(fn, entry->d_name); } else { @@ -260,26 +275,26 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) } } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); #else - strcpy(fn, next_fn); + strcpy(fn, handle->next_fn); - strcpy(next_fn, ""); - WIN32_FIND_DATA fdata; + strcpy(handle->next_fn, ""); + WIN32_FIND_DATAA fdata; - if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; + if(FindNextFileA(handle->dir_p, &fdata) == false) return LV_FS_RES_OK; do { if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { continue; } else { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); } else { - sprintf(next_fn, "%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); } break; } - } while(FindNextFile(dir_p, &fdata)); + } while(FindNextFileA(handle->dir_p, &fdata)); #endif return LV_FS_RES_OK; @@ -294,11 +309,13 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) { LV_UNUSED(drv); + dir_handle_t * handle = (dir_handle_t *)dir_p; #ifndef WIN32 - closedir(dir_p); + closedir(handle->dir_p); #else - FindClose(dir_p); + FindClose(handle->dir_p); #endif + lv_mem_free(handle); return LV_FS_RES_OK; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c index ad4536d40..1a59aa496 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c @@ -16,10 +16,16 @@ /********************* * DEFINES *********************/ +#define MAX_PATH_LEN 256 /********************** * TYPEDEFS **********************/ +typedef struct { + HANDLE dir_p; + char next_fn[MAX_PATH_LEN]; + lv_fs_res_t next_error; +} dir_handle_t; /********************** * STATIC PROTOTYPES @@ -58,7 +64,7 @@ void lv_fs_win32_init(void) * Register the file system interface in LVGL *--------------------------------------------------*/ - /*Add a simple drive to open images*/ + /*Add a simple driver to open images*/ static lv_fs_drv_t fs_drv; /*A driver descriptor*/ lv_fs_drv_init(&fs_drv); @@ -213,7 +219,7 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) /*Make the path relative to the current directory (the projects root folder)*/ char buf[MAX_PATH]; - sprintf(buf, LV_FS_WIN32_PATH "%s", path); + lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s", path); return (void *)CreateFileA( buf, @@ -263,8 +269,8 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ * @param drv pointer to a driver where this function belongs * @param file_p pointer to a FILE variable * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -344,9 +350,6 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) } } -static char next_fn[256]; -static lv_fs_res_t next_error = LV_FS_RES_OK; - /** * Initialize a 'DIR' or 'HANDLE' variable for directory reading * @param drv pointer to a driver where this function belongs @@ -356,38 +359,45 @@ static lv_fs_res_t next_error = LV_FS_RES_OK; static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); - - HANDLE d = INVALID_HANDLE_VALUE; + dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t)); + handle->dir_p = INVALID_HANDLE_VALUE; + handle->next_error = LV_FS_RES_OK; WIN32_FIND_DATAA fdata; /*Make the path relative to the current directory (the projects root folder)*/ - char buf[256]; + char buf[MAX_PATH_LEN]; #ifdef LV_FS_WIN32_PATH - sprintf(buf, LV_FS_WIN32_PATH "%s\\*", path); + lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s\\*", path); #else - sprintf(buf, "%s\\*", path); + lv_snprintf(buf, sizeof(buf), "%s\\*", path); #endif - strcpy(next_fn, ""); - d = FindFirstFileA(buf, &fdata); + strcpy(handle->next_fn, ""); + handle->dir_p = FindFirstFileA(buf, &fdata); do { if(is_dots_name(fdata.cFileName)) { continue; } else { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); } else { - sprintf(next_fn, "%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); } break; } + } while(FindNextFileA(handle->dir_p, &fdata)); - } while(FindNextFileA(d, &fdata)); - - next_error = fs_error_from_win32(GetLastError()); - return d; + if(handle->dir_p == INVALID_HANDLE_VALUE) { + lv_mem_free(handle); + handle->next_error = fs_error_from_win32(GetLastError()); + return INVALID_HANDLE_VALUE; + } + else { + handle->next_error = LV_FS_RES_OK; + return handle; + } } /** @@ -401,31 +411,30 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) { LV_UNUSED(drv); + dir_handle_t * handle = (dir_handle_t *)dir_p; + strcpy(fn, handle->next_fn); + lv_fs_res_t current_error = handle->next_error; + strcpy(handle->next_fn, ""); - strcpy(fn, next_fn); - lv_fs_res_t current_error = next_error; - next_error = LV_FS_RES_OK; - - strcpy(next_fn, ""); WIN32_FIND_DATAA fdata; - while(FindNextFileA(dir_p, &fdata)) { + while(FindNextFileA(handle->dir_p, &fdata)) { if(is_dots_name(fdata.cFileName)) { continue; } else { if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); } else { - sprintf(next_fn, "%s", fdata.cFileName); + lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); } break; } } - if(next_fn[0] == '\0') { - next_error = fs_error_from_win32(GetLastError()); + if(handle->next_fn[0] == '\0') { + handle->next_error = fs_error_from_win32(GetLastError()); } return current_error; @@ -440,9 +449,12 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) { LV_UNUSED(drv); - return FindClose((HANDLE)dir_p) - ? LV_FS_RES_OK - : fs_error_from_win32(GetLastError()); + dir_handle_t * handle = (dir_handle_t *)dir_p; + lv_fs_res_t res = FindClose(handle->dir_p) + ? LV_FS_RES_OK + : fs_error_from_win32(GetLastError()); + lv_mem_free(handle); + return res; } #else /*LV_USE_FS_WIN32 == 0*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c new file mode 100644 index 000000000..68f50057e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c @@ -0,0 +1,659 @@ +#include "gifdec.h" +#include "../../../misc/lv_log.h" +#include "../../../misc/lv_mem.h" +#include "../../../misc/lv_color.h" +#if LV_USE_GIF + +#include +#include +#include + +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define MAX(A, B) ((A) > (B) ? (A) : (B)) + +typedef struct Entry { + uint16_t length; + uint16_t prefix; + uint8_t suffix; +} Entry; + +typedef struct Table { + int bulk; + int nentries; + Entry *entries; +} Table; + +static gd_GIF * gif_open(gd_GIF * gif); +static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file); +static void f_gif_read(gd_GIF * gif, void * buf, size_t len); +static int f_gif_seek(gd_GIF * gif, size_t pos, int k); +static void f_gif_close(gd_GIF * gif); + +static uint16_t +read_num(gd_GIF * gif) +{ + uint8_t bytes[2]; + + f_gif_read(gif, bytes, 2); + return bytes[0] + (((uint16_t) bytes[1]) << 8); +} + + + +gd_GIF * +gd_open_gif_file(const char *fname) +{ + gd_GIF gif_base; + memset(&gif_base, 0, sizeof(gif_base)); + + bool res = f_gif_open(&gif_base, fname, true); + if(!res) return NULL; + + return gif_open(&gif_base); +} + + +gd_GIF * +gd_open_gif_data(const void *data) +{ + gd_GIF gif_base; + memset(&gif_base, 0, sizeof(gif_base)); + + bool res = f_gif_open(&gif_base, data, false); + if(!res) return NULL; + + return gif_open(&gif_base); +} + +static gd_GIF * gif_open(gd_GIF * gif_base) +{ + uint8_t sigver[3]; + uint16_t width, height, depth; + uint8_t fdsz, bgidx, aspect; + int i; + uint8_t *bgcolor; + int gct_sz; + gd_GIF *gif = NULL; + + /* Header */ + f_gif_read(gif_base, sigver, 3); + if (memcmp(sigver, "GIF", 3) != 0) { + LV_LOG_WARN("invalid signature\n"); + goto fail; + } + /* Version */ + f_gif_read(gif_base, sigver, 3); + if (memcmp(sigver, "89a", 3) != 0) { + LV_LOG_WARN("invalid version\n"); + goto fail; + } + /* Width x Height */ + width = read_num(gif_base); + height = read_num(gif_base); + /* FDSZ */ + f_gif_read(gif_base, &fdsz, 1); + /* Presence of GCT */ + if (!(fdsz & 0x80)) { + LV_LOG_WARN("no global color table\n"); + goto fail; + } + /* Color Space's Depth */ + depth = ((fdsz >> 4) & 7) + 1; + /* Ignore Sort Flag. */ + /* GCT Size */ + gct_sz = 1 << ((fdsz & 0x07) + 1); + /* Background Color Index */ + f_gif_read(gif_base, &bgidx, 1); + /* Aspect Ratio */ + f_gif_read(gif_base, &aspect, 1); + /* Create gd_GIF Structure. */ +#if LV_COLOR_DEPTH == 32 + gif = lv_mem_alloc(sizeof(gd_GIF) + 5 * width * height); +#elif LV_COLOR_DEPTH == 16 + gif = lv_mem_alloc(sizeof(gd_GIF) + 4 * width * height); +#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + gif = lv_mem_alloc(sizeof(gd_GIF) + 3 * width * height); +#endif + + if (!gif) goto fail; + memcpy(gif, gif_base, sizeof(gd_GIF)); + gif->width = width; + gif->height = height; + gif->depth = depth; + /* Read GCT */ + gif->gct.size = gct_sz; + f_gif_read(gif, gif->gct.colors, 3 * gif->gct.size); + gif->palette = &gif->gct; + gif->bgindex = bgidx; + gif->canvas = (uint8_t *) &gif[1]; +#if LV_COLOR_DEPTH == 32 + gif->frame = &gif->canvas[4 * width * height]; +#elif LV_COLOR_DEPTH == 16 + gif->frame = &gif->canvas[3 * width * height]; +#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + gif->frame = &gif->canvas[2 * width * height]; +#endif + if (gif->bgindex) { + memset(gif->frame, gif->bgindex, gif->width * gif->height); + } + bgcolor = &gif->palette->colors[gif->bgindex*3]; + + for (i = 0; i < gif->width * gif->height; i++) { +#if LV_COLOR_DEPTH == 32 + gif->canvas[i*4 + 0] = *(bgcolor + 2); + gif->canvas[i*4 + 1] = *(bgcolor + 1); + gif->canvas[i*4 + 2] = *(bgcolor + 0); + gif->canvas[i*4 + 3] = 0xff; +#elif LV_COLOR_DEPTH == 16 + lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); + gif->canvas[i*3 + 0] = c.full & 0xff; + gif->canvas[i*3 + 1] = (c.full >> 8) & 0xff; + gif->canvas[i*3 + 2] = 0xff; +#elif LV_COLOR_DEPTH == 8 + lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); + gif->canvas[i*2 + 0] = c.full; + gif->canvas[i*2 + 1] = 0xff; +#elif LV_COLOR_DEPTH == 1 + lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); + gif->canvas[i*2 + 0] = c.ch.red > 128 ? 1 : 0; + gif->canvas[i*2 + 1] = 0xff; +#endif + } + gif->anim_start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + goto ok; +fail: + f_gif_close(gif_base); +ok: + return gif; +} + +static void +discard_sub_blocks(gd_GIF *gif) +{ + uint8_t size; + + do { + f_gif_read(gif, &size, 1); + f_gif_seek(gif, size, LV_FS_SEEK_CUR); + } while (size); +} + +static void +read_plain_text_ext(gd_GIF *gif) +{ + if (gif->plain_text) { + uint16_t tx, ty, tw, th; + uint8_t cw, ch, fg, bg; + size_t sub_block; + f_gif_seek(gif, 1, LV_FS_SEEK_CUR); /* block size = 12 */ + tx = read_num(gif); + ty = read_num(gif); + tw = read_num(gif); + th = read_num(gif); + f_gif_read(gif, &cw, 1); + f_gif_read(gif, &ch, 1); + f_gif_read(gif, &fg, 1); + f_gif_read(gif, &bg, 1); + sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg); + f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); + } else { + /* Discard plain text metadata. */ + f_gif_seek(gif, 13, LV_FS_SEEK_CUR); + } + /* Discard plain text sub-blocks. */ + discard_sub_blocks(gif); +} + +static void +read_graphic_control_ext(gd_GIF *gif) +{ + uint8_t rdit; + + /* Discard block size (always 0x04). */ + f_gif_seek(gif, 1, LV_FS_SEEK_CUR); + f_gif_read(gif, &rdit, 1); + gif->gce.disposal = (rdit >> 2) & 3; + gif->gce.input = rdit & 2; + gif->gce.transparency = rdit & 1; + gif->gce.delay = read_num(gif); + f_gif_read(gif, &gif->gce.tindex, 1); + /* Skip block terminator. */ + f_gif_seek(gif, 1, LV_FS_SEEK_CUR); +} + +static void +read_comment_ext(gd_GIF *gif) +{ + if (gif->comment) { + size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + gif->comment(gif); + f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); + } + /* Discard comment sub-blocks. */ + discard_sub_blocks(gif); +} + +static void +read_application_ext(gd_GIF *gif) +{ + char app_id[8]; + char app_auth_code[3]; + + /* Discard block size (always 0x0B). */ + f_gif_seek(gif, 1, LV_FS_SEEK_CUR); + /* Application Identifier. */ + f_gif_read(gif, app_id, 8); + /* Application Authentication Code. */ + f_gif_read(gif, app_auth_code, 3); + if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) { + /* Discard block size (0x03) and constant byte (0x01). */ + f_gif_seek(gif, 2, LV_FS_SEEK_CUR); + gif->loop_count = read_num(gif); + /* Skip block terminator. */ + f_gif_seek(gif, 1, LV_FS_SEEK_CUR); + } else if (gif->application) { + size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + gif->application(gif, app_id, app_auth_code); + f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); + discard_sub_blocks(gif); + } else { + discard_sub_blocks(gif); + } +} + +static void +read_ext(gd_GIF *gif) +{ + uint8_t label; + + f_gif_read(gif, &label, 1); + switch (label) { + case 0x01: + read_plain_text_ext(gif); + break; + case 0xF9: + read_graphic_control_ext(gif); + break; + case 0xFE: + read_comment_ext(gif); + break; + case 0xFF: + read_application_ext(gif); + break; + default: + LV_LOG_WARN("unknown extension: %02X\n", label); + } +} + +static Table * +new_table(int key_size) +{ + int key; + int init_bulk = MAX(1 << (key_size + 1), 0x100); + Table *table = lv_mem_alloc(sizeof(*table) + sizeof(Entry) * init_bulk); + if (table) { + table->bulk = init_bulk; + table->nentries = (1 << key_size) + 2; + table->entries = (Entry *) &table[1]; + for (key = 0; key < (1 << key_size); key++) + table->entries[key] = (Entry) {1, 0xFFF, key}; + } + return table; +} + +/* Add table entry. Return value: + * 0 on success + * +1 if key size must be incremented after this addition + * -1 if could not realloc table */ +static int +add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix) +{ + Table *table = *tablep; + if (table->nentries == table->bulk) { + table->bulk *= 2; + table = lv_mem_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); + if (!table) return -1; + table->entries = (Entry *) &table[1]; + *tablep = table; + } + table->entries[table->nentries] = (Entry) {length, prefix, suffix}; + table->nentries++; + if ((table->nentries & (table->nentries - 1)) == 0) + return 1; + return 0; +} + +static uint16_t +get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte) +{ + int bits_read; + int rpad; + int frag_size; + uint16_t key; + + key = 0; + for (bits_read = 0; bits_read < key_size; bits_read += frag_size) { + rpad = (*shift + bits_read) % 8; + if (rpad == 0) { + /* Update byte. */ + if (*sub_len == 0) { + f_gif_read(gif, sub_len, 1); /* Must be nonzero! */ + if (*sub_len == 0) return 0x1000; + } + f_gif_read(gif, byte, 1); + (*sub_len)--; + } + frag_size = MIN(key_size - bits_read, 8 - rpad); + key |= ((uint16_t) ((*byte) >> rpad)) << bits_read; + } + /* Clear extra bits to the left. */ + key &= (1 << key_size) - 1; + *shift = (*shift + key_size) % 8; + return key; +} + +/* Compute output index of y-th input line, in frame of height h. */ +static int +interlaced_line_index(int h, int y) +{ + int p; /* number of lines in current pass */ + + p = (h - 1) / 8 + 1; + if (y < p) /* pass 1 */ + return y * 8; + y -= p; + p = (h - 5) / 8 + 1; + if (y < p) /* pass 2 */ + return y * 8 + 4; + y -= p; + p = (h - 3) / 4 + 1; + if (y < p) /* pass 3 */ + return y * 4 + 2; + y -= p; + /* pass 4 */ + return y * 2 + 1; +} + +/* Decompress image pixels. + * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */ +static int +read_image_data(gd_GIF *gif, int interlace) +{ + uint8_t sub_len, shift, byte; + int init_key_size, key_size, table_is_full=0; + int frm_off, frm_size, str_len=0, i, p, x, y; + uint16_t key, clear, stop; + int ret; + Table *table; + Entry entry = {0}; + size_t start, end; + + f_gif_read(gif, &byte, 1); + key_size = (int) byte; + start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + discard_sub_blocks(gif); + end = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + f_gif_seek(gif, start, LV_FS_SEEK_SET); + clear = 1 << key_size; + stop = clear + 1; + table = new_table(key_size); + key_size++; + init_key_size = key_size; + sub_len = shift = 0; + key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */ + frm_off = 0; + ret = 0; + frm_size = gif->fw*gif->fh; + while (frm_off < frm_size) { + if (key == clear) { + key_size = init_key_size; + table->nentries = (1 << (key_size - 1)) + 2; + table_is_full = 0; + } else if (!table_is_full) { + ret = add_entry(&table, str_len + 1, key, entry.suffix); + if (ret == -1) { + lv_mem_free(table); + return -1; + } + if (table->nentries == 0x1000) { + ret = 0; + table_is_full = 1; + } + } + key = get_key(gif, key_size, &sub_len, &shift, &byte); + if (key == clear) continue; + if (key == stop || key == 0x1000) break; + if (ret == 1) key_size++; + entry = table->entries[key]; + str_len = entry.length; + for (i = 0; i < str_len; i++) { + p = frm_off + entry.length - 1; + x = p % gif->fw; + y = p / gif->fw; + if (interlace) + y = interlaced_line_index((int) gif->fh, y); + gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix; + if (entry.prefix == 0xFFF) + break; + else + entry = table->entries[entry.prefix]; + } + frm_off += str_len; + if (key < table->nentries - 1 && !table_is_full) + table->entries[table->nentries - 1].suffix = entry.suffix; + } + lv_mem_free(table); + if (key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ + f_gif_seek(gif, end, LV_FS_SEEK_SET); + return 0; +} + +/* Read image. + * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */ +static int +read_image(gd_GIF *gif) +{ + uint8_t fisrz; + int interlace; + + /* Image Descriptor. */ + gif->fx = read_num(gif); + gif->fy = read_num(gif); + gif->fw = read_num(gif); + gif->fh = read_num(gif); + f_gif_read(gif, &fisrz, 1); + interlace = fisrz & 0x40; + /* Ignore Sort Flag. */ + /* Local Color Table? */ + if (fisrz & 0x80) { + /* Read LCT */ + gif->lct.size = 1 << ((fisrz & 0x07) + 1); + f_gif_read(gif, gif->lct.colors, 3 * gif->lct.size); + gif->palette = &gif->lct; + } else + gif->palette = &gif->gct; + /* Image Data. */ + return read_image_data(gif, interlace); +} + +static void +render_frame_rect(gd_GIF *gif, uint8_t *buffer) +{ + int i, j, k; + uint8_t index, *color; + i = gif->fy * gif->width + gif->fx; + for (j = 0; j < gif->fh; j++) { + for (k = 0; k < gif->fw; k++) { + index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k]; + color = &gif->palette->colors[index*3]; + if (!gif->gce.transparency || index != gif->gce.tindex) { +#if LV_COLOR_DEPTH == 32 + buffer[(i+k)*4 + 0] = *(color + 2); + buffer[(i+k)*4 + 1] = *(color + 1); + buffer[(i+k)*4 + 2] = *(color + 0); + buffer[(i+k)*4 + 3] = 0xFF; +#elif LV_COLOR_DEPTH == 16 + lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2)); + buffer[(i+k)*3 + 0] = c.full & 0xff; + buffer[(i+k)*3 + 1] = (c.full >> 8) & 0xff; + buffer[(i+k)*3 + 2] = 0xff; +#elif LV_COLOR_DEPTH == 8 + lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2)); + buffer[(i+k)*2 + 0] = c.full; + buffer[(i+k)*2 + 1] = 0xff; +#elif LV_COLOR_DEPTH == 1 + uint8_t b = (*(color + 0)) | (*(color + 1)) | (*(color + 2)); + buffer[(i+k)*2 + 0] = b > 128 ? 1 : 0; + buffer[(i+k)*2 + 1] = 0xff; +#endif + } + } + i += gif->width; + } +} + +static void +dispose(gd_GIF *gif) +{ + int i, j, k; + uint8_t *bgcolor; + switch (gif->gce.disposal) { + case 2: /* Restore to background color. */ + bgcolor = &gif->palette->colors[gif->bgindex*3]; + + uint8_t opa = 0xff; + if(gif->gce.transparency) opa = 0x00; + + i = gif->fy * gif->width + gif->fx; + for (j = 0; j < gif->fh; j++) { + for (k = 0; k < gif->fw; k++) { +#if LV_COLOR_DEPTH == 32 + gif->canvas[(i+k)*4 + 0] = *(bgcolor + 2); + gif->canvas[(i+k)*4 + 1] = *(bgcolor + 1); + gif->canvas[(i+k)*4 + 2] = *(bgcolor + 0); + gif->canvas[(i+k)*4 + 3] = opa; +#elif LV_COLOR_DEPTH == 16 + lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); + gif->canvas[(i+k)*3 + 0] = c.full & 0xff; + gif->canvas[(i+k)*3 + 1] = (c.full >> 8) & 0xff; + gif->canvas[(i+k)*3 + 2] = opa; +#elif LV_COLOR_DEPTH == 8 + lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); + gif->canvas[(i+k)*2 + 0] = c.full; + gif->canvas[(i+k)*2 + 1] = opa; +#elif LV_COLOR_DEPTH == 1 + uint8_t b = (*(bgcolor + 0)) | (*(bgcolor + 1)) | (*(bgcolor + 2)); + gif->canvas[(i+k)*2 + 0] = b > 128 ? 1 : 0; + gif->canvas[(i+k)*2 + 1] = opa; +#endif + } + i += gif->width; + } + break; + case 3: /* Restore to previous, i.e., don't update canvas.*/ + break; + default: + /* Add frame non-transparent pixels to canvas. */ + render_frame_rect(gif, gif->canvas); + } +} + +/* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */ +int +gd_get_frame(gd_GIF *gif) +{ + char sep; + + dispose(gif); + f_gif_read(gif, &sep, 1); + while (sep != ',') { + if (sep == ';') + return 0; + if (sep == '!') + read_ext(gif); + else return -1; + f_gif_read(gif, &sep, 1); + } + if (read_image(gif) == -1) + return -1; + return 1; +} + +void +gd_render_frame(gd_GIF *gif, uint8_t *buffer) +{ +// uint32_t i; +// uint32_t j; +// for(i = 0, j = 0; i < gif->width * gif->height * 3; i+= 3, j+=4) { +// buffer[j + 0] = gif->canvas[i + 2]; +// buffer[j + 1] = gif->canvas[i + 1]; +// buffer[j + 2] = gif->canvas[i + 0]; +// buffer[j + 3] = 0xFF; +// } +// memcpy(buffer, gif->canvas, gif->width * gif->height * 3); + render_frame_rect(gif, buffer); +} + +void +gd_rewind(gd_GIF *gif) +{ + f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET); +} + +void +gd_close_gif(gd_GIF *gif) +{ + f_gif_close(gif); + lv_mem_free(gif); +} + +static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file) +{ + gif->f_rw_p = 0; + gif->data = NULL; + gif->is_file = is_file; + + if(is_file) { + lv_fs_res_t res = lv_fs_open(&gif->fd, path, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return false; + else return true; + } else { + gif->data = path; + return true; + } +} + +static void f_gif_read(gd_GIF * gif, void * buf, size_t len) +{ + if(gif->is_file) { + lv_fs_read(&gif->fd, buf, len, NULL); + } else + { + memcpy(buf, &gif->data[gif->f_rw_p], len); + gif->f_rw_p += len; + } +} + +static int f_gif_seek(gd_GIF * gif, size_t pos, int k) +{ + if(gif->is_file) { + lv_fs_seek(&gif->fd, pos, k); + uint32_t x; + lv_fs_tell(&gif->fd, &x); + return x; + } else { + if(k == LV_FS_SEEK_CUR) gif->f_rw_p += pos; + else if(k == LV_FS_SEEK_SET) gif->f_rw_p = pos; + return gif->f_rw_p; + } +} + +static void f_gif_close(gd_GIF * gif) +{ + if(gif->is_file) { + lv_fs_close(&gif->fd); + } +} + +#endif /*LV_USE_GIF*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h new file mode 100644 index 000000000..00f17c1da --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h @@ -0,0 +1,60 @@ +#ifndef GIFDEC_H +#define GIFDEC_H + +#include +#include "../../../misc/lv_fs.h" + +#if LV_USE_GIF + +typedef struct gd_Palette { + int size; + uint8_t colors[0x100 * 3]; +} gd_Palette; + +typedef struct gd_GCE { + uint16_t delay; + uint8_t tindex; + uint8_t disposal; + int input; + int transparency; +} gd_GCE; + + + +typedef struct gd_GIF { + lv_fs_file_t fd; + const char * data; + uint8_t is_file; + uint32_t f_rw_p; + int32_t anim_start; + uint16_t width, height; + uint16_t depth; + uint16_t loop_count; + gd_GCE gce; + gd_Palette *palette; + gd_Palette lct, gct; + void (*plain_text)( + struct gd_GIF *gif, uint16_t tx, uint16_t ty, + uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch, + uint8_t fg, uint8_t bg + ); + void (*comment)(struct gd_GIF *gif); + void (*application)(struct gd_GIF *gif, char id[8], char auth[3]); + uint16_t fx, fy, fw, fh; + uint8_t bgindex; + uint8_t *canvas, *frame; +} gd_GIF; + +gd_GIF * gd_open_gif_file(const char *fname); + +gd_GIF * gd_open_gif_data(const void *data); + +void gd_render_frame(gd_GIF *gif, uint8_t *buffer); + +int gd_get_frame(gd_GIF *gif); +void gd_rewind(gd_GIF *gif); +void gd_close_gif(gd_GIF *gif); + +#endif /*LV_USE_GIF*/ + +#endif /* GIFDEC_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c new file mode 100644 index 000000000..4cb2955e2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c @@ -0,0 +1,155 @@ +/** + * @file lv_gifenc.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_gif.h" +#if LV_USE_GIF + +#include "gifdec.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_gif_class + +/********************** + * TYPEDEFS + **********************/ + + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void next_frame_task_cb(lv_timer_t * t); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_gif_class = { + .constructor_cb = lv_gif_constructor, + .destructor_cb = lv_gif_destructor, + .instance_size = sizeof(lv_gif_t), + .base_class = &lv_img_class +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_gif_create(lv_obj_t * parent) +{ + + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +void lv_gif_set_src(lv_obj_t * obj, const void * src) +{ + lv_gif_t * gifobj = (lv_gif_t *) obj; + + /*Close previous gif if any*/ + if(gifobj->gif) { + lv_img_cache_invalidate_src(&gifobj->imgdsc); + gd_close_gif(gifobj->gif); + gifobj->gif = NULL; + gifobj->imgdsc.data = NULL; + } + + if(lv_img_src_get_type(src) == LV_IMG_SRC_VARIABLE) { + const lv_img_dsc_t * img_dsc = src; + gifobj->gif = gd_open_gif_data(img_dsc->data); + } + else if(lv_img_src_get_type(src) == LV_IMG_SRC_FILE) { + gifobj->gif = gd_open_gif_file(src); + } + if(gifobj->gif == NULL) { + LV_LOG_WARN("Could't load the source"); + return; + } + + gifobj->imgdsc.data = gifobj->gif->canvas; + gifobj->imgdsc.header.always_zero = 0; + gifobj->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + gifobj->imgdsc.header.h = gifobj->gif->height; + gifobj->imgdsc.header.w = gifobj->gif->width; + gifobj->last_call = lv_tick_get(); + + lv_img_set_src(obj, &gifobj->imgdsc); + + lv_timer_resume(gifobj->timer); + lv_timer_reset(gifobj->timer); + + next_frame_task_cb(gifobj->timer); + +} + +void lv_gif_restart(lv_obj_t * obj) +{ + lv_gif_t * gifobj = (lv_gif_t *) obj; + gd_rewind(gifobj->gif); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + + lv_gif_t * gifobj = (lv_gif_t *) obj; + + gifobj->timer = lv_timer_create(next_frame_task_cb, 10, obj); + lv_timer_pause(gifobj->timer); +} + +static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_gif_t * gifobj = (lv_gif_t *) obj; + lv_img_cache_invalidate_src(&gifobj->imgdsc); + gd_close_gif(gifobj->gif); + lv_timer_del(gifobj->timer); +} + +static void next_frame_task_cb(lv_timer_t * t) +{ + lv_obj_t * obj = t->user_data; + lv_gif_t * gifobj = (lv_gif_t *) obj; + uint32_t elaps = lv_tick_elaps(gifobj->last_call); + if(elaps < gifobj->gif->gce.delay * 10) return; + + gifobj->last_call = lv_tick_get(); + + int has_next = gd_get_frame(gifobj->gif); + if(has_next == 0) { + /*It was the last repeat*/ + if(gifobj->gif->loop_count == 1) { + lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL); + if(res != LV_FS_RES_OK) return; + } + else { + if(gifobj->gif->loop_count > 1) gifobj->gif->loop_count--; + gd_rewind(gifobj->gif); + } + } + + gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data); + + lv_img_cache_invalidate_src(lv_img_get_src(obj)); + lv_obj_invalidate(obj); +} + +#endif /*LV_USE_GIF*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h new file mode 100644 index 000000000..d8c93dbc0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h @@ -0,0 +1,58 @@ +/** + * @file lv_gif.h + * + */ + +#ifndef LV_GIF_H +#define LV_GIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_GIF + +#include "gifdec.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_img_t img; + gd_GIF * gif; + lv_timer_t * timer; + lv_img_dsc_t imgdsc; + uint32_t last_call; +} lv_gif_t; + +extern const lv_obj_class_t lv_gif_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_gif_create(lv_obj_t * parent); +void lv_gif_set_src(lv_obj_t * obj, const void * src); +void lv_gif_restart(lv_obj_t * gif); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GIF*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_GIF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h index e795f4c76..6782b1d08 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h @@ -13,15 +13,15 @@ extern "C" { /********************* * INCLUDES *********************/ -// #include "bmp/lv_bmp.h" -// #include "fsdrv/lv_fsdrv.h" +#include "bmp/lv_bmp.h" +#include "fsdrv/lv_fsdrv.h" #include "png/lv_png.h" -// #include "gif/lv_gif.h" +#include "gif/lv_gif.h" #include "qrcode/lv_qrcode.h" -// #include "sjpg/lv_sjpg.h" +#include "sjpg/lv_sjpg.h" #include "freetype/lv_freetype.h" -// #include "rlottie/lv_rlottie.h" -// #include "ffmpeg/lv_ffmpeg.h" +#include "rlottie/lv_rlottie.h" +#include "ffmpeg/lv_ffmpeg.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c index 65139bc5b..82e18e1a0 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c @@ -119,14 +119,12 @@ to something as fast. */ static void lodepng_memcpy(void* LODEPNG_RESTRICT dst, const void* LODEPNG_RESTRICT src, size_t size) { - size_t i; - for(i = 0; i < size; i++) ((char*)dst)[i] = ((const char*)src)[i]; + lv_memcpy(dst, src, size); } static void lodepng_memset(void* LODEPNG_RESTRICT dst, int value, size_t num) { - size_t i; - for(i = 0; i < num; i++) ((char*)dst)[i] = (char)value; + lv_memset(dst, value, num); } /* does not check memory out of bounds, do not use on untrusted data */ @@ -5756,7 +5754,7 @@ static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const adam7 = (unsigned char*)lodepng_malloc(passstart[7]); if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ - if(!error) { + if(!error && adam7) { unsigned i; Adam7_interlace(adam7, in, w, h, bpp); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c index 0b88eb89a..d067ef508 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c @@ -70,7 +70,7 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr /*If it's a PNG file...*/ if(src_type == LV_IMG_SRC_FILE) { const char * fn = src; - if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/ + if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ /* Read the width and height from the file. They have a constant location: * [16..23]: width @@ -80,14 +80,18 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr lv_fs_file_t f; lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); if(res != LV_FS_RES_OK) return LV_RES_INV; + lv_fs_seek(&f, 16, LV_FS_SEEK_SET); + uint32_t rn; lv_fs_read(&f, &size, 8, &rn); - if(rn != 8) return LV_RES_INV; lv_fs_close(&f); + + if(rn != 8) return LV_RES_INV; + /*Save the data in the header*/ header->always_zero = 0; - header->cf = LV_IMG_CF_RAW_ALPHA; + header->cf = LV_IMG_CF_TRUE_COLOR_ALPHA; /*The width and height are stored in Big endian format so convert them to little endian*/ header->w = (lv_coord_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); header->h = (lv_coord_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); @@ -98,7 +102,9 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr /*If it's a PNG file in a C array...*/ else if(src_type == LV_IMG_SRC_VARIABLE) { const lv_img_dsc_t * img_dsc = src; + const uint32_t data_size = img_dsc->data_size; const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; + if(data_size < sizeof(magic)) return LV_RES_INV; if(memcmp(magic, img_dsc->data, sizeof(magic))) return LV_RES_INV; header->always_zero = 0; header->cf = img_dsc->header.cf; /*Save the color format*/ @@ -115,7 +121,7 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr * Open a PNG image and return the decided image * @param src can be file name or pointer to a C array * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed + * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed */ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) { @@ -128,8 +134,7 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * /*If it's a PNG file...*/ if(dsc->src_type == LV_IMG_SRC_FILE) { const char * fn = dsc->src; - - if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/ + if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ /*Load the PNG file into buffer. It's still compressed (not decoded)*/ unsigned char * png_data; /*Pointer to the loaded data. Same as the original file just loaded into the RAM*/ @@ -149,6 +154,9 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size); lv_mem_free(png_data); /*Free the loaded file*/ if(error) { + if(img_data != NULL) { + lv_mem_free(img_data); + } LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error)); return LV_RES_INV; } @@ -169,6 +177,9 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * error = lodepng_decode32(&img_data, &png_width, &png_height, img_dsc->data, img_dsc->data_size); if(error) { + if(img_data != NULL) { + lv_mem_free(img_data); + } return LV_RES_INV; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c index 4b06c78e7..37ee74233 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c @@ -1,9 +1,9 @@ -/* +/* * QR Code generator library (C) - * + * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h index dceddf605..b484e9175 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h @@ -1,9 +1,9 @@ -/* +/* * QR Code generator library (C) - * + * * Copyright (c) Project Nayuki. (MIT License) * https://www.nayuki.io/page/qr-code-generator-library - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to @@ -33,14 +33,14 @@ extern "C" { #endif -/* +/* * This library creates QR Code symbols, which is a type of two-dimension barcode. * Invented by Denso Wave and described in the ISO/IEC 18004 standard. * A QR Code structure is an immutable square grid of black and white cells. * The library provides functions to create a QR Code from text or binary data. * The library covers the QR Code Model 2 specification, supporting all versions (sizes) * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. - * + * * Ways to create a QR Code object: * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). * - Low level: Custom-make the list of segments and call @@ -51,7 +51,7 @@ extern "C" { /*---- Enum and struct types----*/ -/* +/* * The error correction level in a QR Code symbol. */ enum qrcodegen_Ecc { @@ -64,7 +64,7 @@ enum qrcodegen_Ecc { }; -/* +/* * The mask pattern used in a QR Code symbol. */ enum qrcodegen_Mask { @@ -83,7 +83,7 @@ enum qrcodegen_Mask { }; -/* +/* * Describes how a segment's data bits are interpreted. */ enum qrcodegen_Mode { @@ -95,7 +95,7 @@ enum qrcodegen_Mode { }; -/* +/* * A segment of character/binary/control data in a QR Code symbol. * The mid-level way to create a segment is to take the payload data * and call a factory function such as qrcodegen_makeNumeric(). @@ -147,7 +147,7 @@ struct qrcodegen_Segment { /*---- Functions (high level) to generate QR Codes ----*/ -/* +/* * Encodes the given text string to a QR Code, returning true if encoding succeeded. * If the data is too long to fit in any version in the given range * at the given ECC level, then false is returned. @@ -170,7 +170,7 @@ bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); -/* +/* * Encodes the given binary data to a QR Code, returning true if encoding succeeded. * If the data is too long to fit in any version in the given range * at the given ECC level, then false is returned. @@ -194,7 +194,7 @@ bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcod /*---- Functions (low level) to generate QR Codes ----*/ -/* +/* * Renders a QR Code representing the given segments at the given error correction level. * The smallest possible QR Code version is automatically chosen for the output. Returns true if * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level @@ -210,7 +210,7 @@ bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); -/* +/* * Renders a QR Code representing the given segments with the given encoding parameters. * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. * The smallest possible QR Code version within the given range is automatically @@ -229,7 +229,7 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); -/* +/* * Tests whether the given string can be encoded as a segment in alphanumeric mode. * A string is encodable iff each character is in the following set: 0 to 9, A to Z * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. @@ -237,14 +237,14 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz bool qrcodegen_isAlphanumeric(const char *text); -/* +/* * Tests whether the given string can be encoded as a segment in numeric mode. * A string is encodable iff each character is in the range 0 to 9. */ bool qrcodegen_isNumeric(const char *text); -/* +/* * Returns the number of bytes (uint8_t) needed for the data buffer of a segment * containing the given number of characters using the given mode. Notes: * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or @@ -258,7 +258,7 @@ bool qrcodegen_isNumeric(const char *text); size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); -/* +/* * Returns a segment representing the given binary data encoded in * byte mode. All input byte arrays are acceptable. Any text string * can be converted to UTF-8 bytes and encoded as a byte mode segment. @@ -266,13 +266,13 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); -/* +/* * Returns a segment representing the given string of decimal digits encoded in numeric mode. */ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); -/* +/* * Returns a segment representing the given text string encoded in alphanumeric mode. * The characters allowed are: 0 to 9, A to Z (uppercase only), space, * dollar, percent, asterisk, plus, hyphen, period, slash, colon. @@ -280,7 +280,7 @@ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[] struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); -/* +/* * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the given assignment value. */ @@ -289,7 +289,7 @@ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); /*---- Functions to extract raw data from QR Codes ----*/ -/* +/* * Returns the side length of the given QR Code, assuming that encoding succeeded. * The result is in the range [21, 177]. Note that the length of the array buffer * is related to the side length - every 'uint8_t qrcode[]' must have length at least @@ -298,18 +298,18 @@ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); int qrcodegen_getSize(const uint8_t qrcode[]); -/* +/* * Returns the color of the module (pixel) at the given coordinates, which is false * for white or true for black. The top left corner has the coordinates (x=0, y=0). * If the given coordinates are out of bounds, then false (white) is returned. */ bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); -/* +/* * Returns the qrcode size of the specified version. Returns -1 on failure */ int qrcodegen_version2size(int version); -/* +/* * Returns the min version of the data that can be stored. Returns -1 on failure */ int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c new file mode 100644 index 000000000..a264948c3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c @@ -0,0 +1,284 @@ +/** + * @file lv_rlottie.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_rlottie.h" +#if LV_USE_RLOTTIE + +#include + +/********************* +* DEFINES +*********************/ +#define MY_CLASS &lv_rlottie_class +#define LV_ARGB32 32 + +/********************** +* TYPEDEFS +**********************/ +#define LV_ARGB32 32 + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void next_frame_task_cb(lv_timer_t * t); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_rlottie_class = { + .constructor_cb = lv_rlottie_constructor, + .destructor_cb = lv_rlottie_destructor, + .instance_size = sizeof(lv_rlottie_t), + .base_class = &lv_img_class +}; + +static lv_coord_t create_width; +static lv_coord_t create_height; +static const char * rlottie_desc_create; +static const char * path_create; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * path) +{ + + create_width = width; + create_height = height; + path_create = path; + rlottie_desc_create = NULL; + + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + + return obj; + +} + +lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * rlottie_desc) +{ + + create_width = width; + create_height = height; + rlottie_desc_create = rlottie_desc; + path_create = NULL; + + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + + return obj; +} + +void lv_rlottie_set_play_mode(lv_obj_t * obj, const lv_rlottie_ctrl_t ctrl) +{ + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + rlottie->play_ctrl = ctrl; + + if(rlottie->task && (rlottie->dest_frame != rlottie->current_frame || + (rlottie->play_ctrl & LV_RLOTTIE_CTRL_PAUSE) == LV_RLOTTIE_CTRL_PLAY)) { + lv_timer_resume(rlottie->task); + } +} + +void lv_rlottie_set_current_frame(lv_obj_t * obj, const size_t goto_frame) +{ + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + rlottie->current_frame = goto_frame < rlottie->total_frames ? goto_frame : rlottie->total_frames - 1; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + + if(rlottie_desc_create) { + rlottie->animation = lottie_animation_from_data(rlottie_desc_create, rlottie_desc_create, ""); + } + else if(path_create) { + rlottie->animation = lottie_animation_from_file(path_create); + } + if(rlottie->animation == NULL) { + LV_LOG_WARN("The aniamtion can't be opened"); + return; + } + + rlottie->total_frames = lottie_animation_get_totalframe(rlottie->animation); + rlottie->framerate = (size_t)lottie_animation_get_framerate(rlottie->animation); + rlottie->current_frame = 0; + + rlottie->scanline_width = create_width * LV_ARGB32 / 8; + + size_t allocaled_buf_size = (create_width * create_height * LV_ARGB32 / 8); + rlottie->allocated_buf = lv_mem_alloc(allocaled_buf_size); + if(rlottie->allocated_buf != NULL) { + rlottie->allocated_buffer_size = allocaled_buf_size; + memset(rlottie->allocated_buf, 0, allocaled_buf_size); + } + + rlottie->imgdsc.header.always_zero = 0; + rlottie->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + rlottie->imgdsc.header.h = create_height; + rlottie->imgdsc.header.w = create_width; + rlottie->imgdsc.data = (void *)rlottie->allocated_buf; + rlottie->imgdsc.data_size = allocaled_buf_size; + + lv_img_set_src(obj, &rlottie->imgdsc); + + rlottie->play_ctrl = LV_RLOTTIE_CTRL_FORWARD | LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_LOOP; + rlottie->dest_frame = rlottie->total_frames; /* invalid destination frame so it's possible to pause on frame 0 */ + + rlottie->task = lv_timer_create(next_frame_task_cb, 1000 / rlottie->framerate, obj); + + lv_obj_update_layout(obj); +} + + +static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + + if(rlottie->animation) { + lottie_animation_destroy(rlottie->animation); + rlottie->animation = 0; + rlottie->current_frame = 0; + rlottie->framerate = 0; + rlottie->scanline_width = 0; + rlottie->total_frames = 0; + } + + if(rlottie->task) { + lv_timer_del(rlottie->task); + rlottie->task = NULL; + rlottie->play_ctrl = LV_RLOTTIE_CTRL_FORWARD; + rlottie->dest_frame = 0; + } + + lv_img_cache_invalidate_src(&rlottie->imgdsc); + if(rlottie->allocated_buf) { + lv_mem_free(rlottie->allocated_buf); + rlottie->allocated_buf = NULL; + rlottie->allocated_buffer_size = 0; + } + +} + +#if LV_COLOR_DEPTH == 16 +static void convert_to_rgba5658(uint32_t * pix, const size_t width, const size_t height) +{ + /* rlottie draws in ARGB32 format, but LVGL only deal with RGB565 format with (optional 8 bit alpha channel) + so convert in place here the received buffer to LVGL format. */ + uint8_t * dest = (uint8_t *)pix; + uint32_t * src = pix; + for(size_t y = 0; y < height; y++) { + /* Convert a 4 bytes per pixel in format ARGB to R5G6B5A8 format + naive way: + r = ((c & 0xFF0000) >> 19) + g = ((c & 0xFF00) >> 10) + b = ((c & 0xFF) >> 3) + rgb565 = (r << 11) | (g << 5) | b + a = c >> 24; + That's 3 mask, 6 bitshift and 2 or operations + + A bit better: + r = ((c & 0xF80000) >> 8) + g = ((c & 0xFC00) >> 5) + b = ((c & 0xFF) >> 3) + rgb565 = r | g | b + a = c >> 24; + That's 3 mask, 3 bitshifts and 2 or operations */ + for(size_t x = 0; x < width; x++) { + uint32_t in = src[x]; +#if LV_COLOR_16_SWAP == 0 + uint16_t r = (uint16_t)(((in & 0xF80000) >> 8) | ((in & 0xFC00) >> 5) | ((in & 0xFF) >> 3)); +#else + /* We want: rrrr rrrr GGGg gggg bbbb bbbb => gggb bbbb rrrr rGGG */ + uint16_t r = (uint16_t)(((in & 0xF80000) >> 16) | ((in & 0xFC00) >> 13) | ((in & 0x1C00) << 3) | ((in & 0xF8) << 5)); +#endif + + lv_memcpy(dest, &r, sizeof(r)); + dest[sizeof(r)] = (uint8_t)(in >> 24); + dest += LV_IMG_PX_SIZE_ALPHA_BYTE; + } + src += width; + } +} +#endif + +static void next_frame_task_cb(lv_timer_t * t) +{ + lv_obj_t * obj = t->user_data; + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + + if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_PAUSE) == LV_RLOTTIE_CTRL_PAUSE) { + if(rlottie->current_frame == rlottie->dest_frame) { + /* Pause the timer too when it has run once to avoid CPU consumption */ + lv_timer_pause(t); + return; + } + rlottie->dest_frame = rlottie->current_frame; + } + else { + if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_BACKWARD) == LV_RLOTTIE_CTRL_BACKWARD) { + if(rlottie->current_frame > 0) + --rlottie->current_frame; + else { /* Looping ? */ + if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_LOOP) == LV_RLOTTIE_CTRL_LOOP) + rlottie->current_frame = rlottie->total_frames - 1; + else { + lv_event_send(obj, LV_EVENT_READY, NULL); + lv_timer_pause(t); + return; + } + } + } + else { + if(rlottie->current_frame < rlottie->total_frames) + ++rlottie->current_frame; + else { /* Looping ? */ + if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_LOOP) == LV_RLOTTIE_CTRL_LOOP) + rlottie->current_frame = 0; + else { + lv_event_send(obj, LV_EVENT_READY, NULL); + lv_timer_pause(t); + return; + } + } + } + } + + lottie_animation_render( + rlottie->animation, + rlottie->current_frame, + rlottie->allocated_buf, + rlottie->imgdsc.header.w, + rlottie->imgdsc.header.h, + rlottie->scanline_width + ); + +#if LV_COLOR_DEPTH == 16 + convert_to_rgba5658(rlottie->allocated_buf, rlottie->imgdsc.header.w, rlottie->imgdsc.header.h); +#endif + + lv_obj_invalidate(obj); +} + +#endif /*LV_USE_RLOTTIE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h new file mode 100644 index 000000000..d66dc22c0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h @@ -0,0 +1,75 @@ +/** + * @file lv_rlottie.h + * + */ + +#ifndef LV_RLOTTIE_H +#define LV_RLOTTIE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_RLOTTIE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_RLOTTIE_CTRL_FORWARD = 0, + LV_RLOTTIE_CTRL_BACKWARD = 1, + LV_RLOTTIE_CTRL_PAUSE = 2, + LV_RLOTTIE_CTRL_PLAY = 0, /* Yes, play = 0 is the default mode */ + LV_RLOTTIE_CTRL_LOOP = 8, +} lv_rlottie_ctrl_t; + +/** definition in lottieanimation_capi.c */ +struct Lottie_Animation_S; +typedef struct { + lv_img_t img_ext; + struct Lottie_Animation_S * animation; + lv_timer_t * task; + lv_img_dsc_t imgdsc; + size_t total_frames; + size_t current_frame; + size_t framerate; + uint32_t * allocated_buf; + size_t allocated_buffer_size; + size_t scanline_width; + lv_rlottie_ctrl_t play_ctrl; + size_t dest_frame; +} lv_rlottie_t; + +extern const lv_obj_class_t lv_rlottie_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * path); + +lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, + const char * rlottie_desc); + +void lv_rlottie_set_play_mode(lv_obj_t * rlottie, const lv_rlottie_ctrl_t ctrl); +void lv_rlottie_set_current_frame(lv_obj_t * rlottie, const size_t goto_frame); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_RLOTTIE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_RLOTTIE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c new file mode 100644 index 000000000..5a12ea251 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c @@ -0,0 +1,917 @@ +/** + * @file lv_sjpg.c + * + */ + +/*---------------------------------------------------------------------------------------------------------------------------------- +/ Added normal JPG support [7/10/2020] +/ ---------- +/ SJPEG is a custom created modified JPEG file format for small embedded platforms. +/ It will contain multiple JPEG fragments all embedded into a single file with a custom header. +/ This makes JPEG decoding easier using any JPEG library. Overall file size will be almost +/ similar to the parent jpeg file. We can generate sjpeg from any jpeg using a python script +/ provided along with this project. +/ (by vinodstanur | 2020 ) +/ SJPEG FILE STRUCTURE +/ -------------------------------------------------------------------------------------------------------------------------------- +/ Bytes | Value | +/ -------------------------------------------------------------------------------------------------------------------------------- +/ +/ 0 - 7 | "_SJPG__" followed by '\0' +/ +/ 8 - 13 | "V1.00" followed by '\0' [VERSION OF SJPG FILE for future compatibiliby] +/ +/ 14 - 15 | X_RESOLUTION (width) [little endian] +/ +/ 16 - 17 | Y_RESOLUTION (height) [little endian] +/ +/ 18 - 19 | TOTAL_FRAMES inside sjpeg [little endian] +/ +/ 20 - 21 | JPEG BLOCK WIDTH (16 normally) [little endian] +/ +/ 22 - [(TOTAL_FRAMES*2 )] | SIZE OF EACH JPEG SPLIT FRAGMENTS (FRAME_INFO_ARRAY) +/ +/ SJPEG data | Each JPEG frame can be extracted from SJPEG data by parsing the FRAME_INFO_ARRAY one time. +/ +/---------------------------------------------------------------------------------------------------------------------------------- +/ JPEG DECODER +/ ------------ +/ We are using TJpgDec - Tiny JPEG Decompressor library from ELM-CHAN for decoding each split-jpeg fragments. +/ The tjpgd.c and tjpgd.h is not modified and those are used as it is. So if any update comes for the tiny-jpeg, +/ just replace those files with updated files. +/---------------------------------------------------------------------------------------------------------------------------------*/ + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_SJPG + +#include "tjpgd.h" +#include "lv_sjpg.h" +#include "../../../misc/lv_fs.h" + +/********************* + * DEFINES + *********************/ +#define TJPGD_WORKBUFF_SIZE 4096 //Recommended by TJPGD libray + +//NEVER EDIT THESE OFFSET VALUES +#define SJPEG_VERSION_OFFSET 8 +#define SJPEG_X_RES_OFFSET 14 +#define SJPEG_y_RES_OFFSET 16 +#define SJPEG_TOTAL_FRAMES_OFFSET 18 +#define SJPEG_BLOCK_WIDTH_OFFSET 20 +#define SJPEG_FRAME_INFO_ARRAY_OFFSET 22 + +/********************** + * TYPEDEFS + **********************/ + +enum io_source_type { + SJPEG_IO_SOURCE_C_ARRAY, + SJPEG_IO_SOURCE_DISK, +}; + +typedef struct { + enum io_source_type type; + lv_fs_file_t lv_file; + uint8_t * img_cache_buff; + int img_cache_x_res; + int img_cache_y_res; + uint8_t * raw_sjpg_data; //Used when type==SJPEG_IO_SOURCE_C_ARRAY. + uint32_t raw_sjpg_data_size; //Num bytes pointed to by raw_sjpg_data. + uint32_t raw_sjpg_data_next_read_pos; //Used for all types. +} io_source_t; + + +typedef struct { + uint8_t * sjpeg_data; + uint32_t sjpeg_data_size; + int sjpeg_x_res; + int sjpeg_y_res; + int sjpeg_total_frames; + int sjpeg_single_frame_height; + int sjpeg_cache_frame_index; + uint8_t ** frame_base_array; //to save base address of each split frames upto sjpeg_total_frames. + int * frame_base_offset; //to save base offset for fseek + uint8_t * frame_cache; + uint8_t * workb; //JPG work buffer for jpeg library + JDEC * tjpeg_jd; + io_source_t io; +} SJPEG; + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); +static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); +static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, + lv_coord_t len, uint8_t * buf); +static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); +static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata); +static int is_jpg(const uint8_t * raw_data, size_t len); +static void lv_sjpg_cleanup(SJPEG * sjpeg); +static void lv_sjpg_free(SJPEG * sjpeg); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_split_jpeg_init(void) +{ + lv_img_decoder_t * dec = lv_img_decoder_create(); + lv_img_decoder_set_info_cb(dec, decoder_info); + lv_img_decoder_set_open_cb(dec, decoder_open); + lv_img_decoder_set_close_cb(dec, decoder_close); + lv_img_decoder_set_read_line_cb(dec, decoder_read_line); +} + +/********************** + * STATIC FUNCTIONS + **********************/ +/** + * Get info about an SJPG / JPG image + * @param decoder pointer to the decoder where this function belongs + * @param src can be file name or pointer to a C array + * @param header store the info here + * @return LV_RES_OK: no error; LV_RES_INV: can't get the info + */ +static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) +{ + LV_UNUSED(decoder); + + /*Check whether the type `src` is known by the decoder*/ + /* Read the SJPG/JPG header and find `width` and `height` */ + + lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/ + + lv_res_t ret = LV_RES_OK; + + if(src_type == LV_IMG_SRC_VARIABLE) { + const lv_img_dsc_t * img_dsc = src; + uint8_t * raw_sjpeg_data = (uint8_t *)img_dsc->data; + const uint32_t raw_sjpeg_data_size = img_dsc->data_size; + + if(!strncmp((char *)raw_sjpeg_data, "_SJPG__", strlen("_SJPG__"))) { + + raw_sjpeg_data += 14; //seek to res info ... refer sjpeg format + header->always_zero = 0; + header->cf = LV_IMG_CF_RAW; + + header->w = *raw_sjpeg_data++; + header->w |= *raw_sjpeg_data++ << 8; + + header->h = *raw_sjpeg_data++; + header->h |= *raw_sjpeg_data++ << 8; + + return ret; + + } + else if(is_jpg(raw_sjpeg_data, raw_sjpeg_data_size) == true) { + header->always_zero = 0; + header->cf = LV_IMG_CF_RAW; + + uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(!workb_temp) return LV_RES_INV; + + io_source_t io_source_temp; + io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY; + io_source_temp.raw_sjpg_data = raw_sjpeg_data; + io_source_temp.raw_sjpg_data_size = raw_sjpeg_data_size; + io_source_temp.raw_sjpg_data_next_read_pos = 0; + + JDEC jd_tmp; + + JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); + if(rc == JDR_OK) { + header->w = jd_tmp.width; + header->h = jd_tmp.height; + + } + else { + ret = LV_RES_INV; + goto end; + } + +end: + lv_mem_free(workb_temp); + + return ret; + + } + } + else if(src_type == LV_IMG_SRC_FILE) { + const char * fn = src; + if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) { + + uint8_t buff[22]; + memset(buff, 0, sizeof(buff)); + + lv_fs_file_t file; + lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return 78; + + uint32_t rn; + res = lv_fs_read(&file, buff, 8, &rn); + if(res != LV_FS_RES_OK || rn != 8) { + lv_fs_close(&file); + return LV_RES_INV; + } + + if(strcmp((char *)buff, "_SJPG__") == 0) { + lv_fs_seek(&file, 14, LV_FS_SEEK_SET); + res = lv_fs_read(&file, buff, 4, &rn); + if(res != LV_FS_RES_OK || rn != 4) { + lv_fs_close(&file); + return LV_RES_INV; + } + header->always_zero = 0; + header->cf = LV_IMG_CF_RAW; + uint8_t * raw_sjpeg_data = buff; + header->w = *raw_sjpeg_data++; + header->w |= *raw_sjpeg_data++ << 8; + header->h = *raw_sjpeg_data++; + header->h |= *raw_sjpeg_data++ << 8; + lv_fs_close(&file); + return LV_RES_OK; + + } + } + else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) { + lv_fs_file_t file; + lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return 78; + + uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(!workb_temp) { + lv_fs_close(&file); + return LV_RES_INV; + } + + io_source_t io_source_temp; + io_source_temp.type = SJPEG_IO_SOURCE_DISK; + io_source_temp.raw_sjpg_data_next_read_pos = 0; + io_source_temp.img_cache_buff = NULL; + io_source_temp.lv_file = file; + JDEC jd_tmp; + + JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); + lv_mem_free(workb_temp); + lv_fs_close(&file); + + if(rc == JDR_OK) { + header->always_zero = 0; + header->cf = LV_IMG_CF_RAW; + header->w = jd_tmp.width; + header->h = jd_tmp.height; + return LV_RES_OK; + } + } + } + return LV_RES_INV; +} + +static int img_data_cb(JDEC * jd, void * data, JRECT * rect) +{ + io_source_t * io = jd->device; + uint8_t * cache = io->img_cache_buff; + const int xres = io->img_cache_x_res; + uint8_t * buf = data; + const int INPUT_PIXEL_SIZE = 3; + const int row_width = rect->right - rect->left + 1; // Row width in pixels. + const int row_size = row_width * INPUT_PIXEL_SIZE; // Row size (bytes). + + for(int y = rect->top; y <= rect->bottom; y++) { + int row_offset = y * xres * INPUT_PIXEL_SIZE + rect->left * INPUT_PIXEL_SIZE; + memcpy(cache + row_offset, buf, row_size); + buf += row_size; + } + + return 1; +} + +static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata) +{ + io_source_t * io = jd->device; + + if(!io) return 0; + + if(io->type == SJPEG_IO_SOURCE_C_ARRAY) { + const uint32_t bytes_left = io->raw_sjpg_data_size - io->raw_sjpg_data_next_read_pos; + const uint32_t to_read = ndata <= bytes_left ? (uint32_t)ndata : bytes_left; + if(to_read == 0) + return 0; + if(buff) { + memcpy(buff, io->raw_sjpg_data + io->raw_sjpg_data_next_read_pos, to_read); + } + io->raw_sjpg_data_next_read_pos += to_read; + return to_read; + } + else if(io->type == SJPEG_IO_SOURCE_DISK) { + + lv_fs_file_t * lv_file_p = &(io->lv_file); + + if(buff) { + uint32_t rn = 0; + lv_fs_read(lv_file_p, buff, (uint32_t)ndata, &rn); + return rn; + } + else { + uint32_t pos; + lv_fs_tell(lv_file_p, &pos); + lv_fs_seek(lv_file_p, (uint32_t)(ndata + pos), LV_FS_SEEK_SET); + return ndata; + } + } + return 0; +} + +/** + * Open SJPG image and return the decided image + * @param decoder pointer to the decoder where this function belongs + * @param dsc pointer to a descriptor which describes this decoding session + * @return LV_RES_OK: no error; LV_RES_INV: can't get the info + */ +static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + lv_res_t lv_ret = LV_RES_OK; + + if(dsc->src_type == LV_IMG_SRC_VARIABLE) { + uint8_t * data; + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + const uint32_t raw_sjpeg_data_size = ((lv_img_dsc_t *)dsc->src)->data_size; + if(sjpeg == NULL) { + sjpeg = lv_mem_alloc(sizeof(SJPEG)); + if(!sjpeg) return LV_RES_INV; + + memset(sjpeg, 0, sizeof(SJPEG)); + + dsc->user_data = sjpeg; + sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; + sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; + } + + if(!strncmp((char *) sjpeg->sjpeg_data, "_SJPG__", strlen("_SJPG__"))) { + + data = sjpeg->sjpeg_data; + data += 14; + + sjpeg->sjpeg_x_res = *data++; + sjpeg->sjpeg_x_res |= *data++ << 8; + + sjpeg->sjpeg_y_res = *data++; + sjpeg->sjpeg_y_res |= *data++ << 8; + + sjpeg->sjpeg_total_frames = *data++; + sjpeg->sjpeg_total_frames |= *data++ << 8; + + sjpeg->sjpeg_single_frame_height = *data++; + sjpeg->sjpeg_single_frame_height |= *data++ << 8; + + sjpeg->frame_base_array = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); + if(! sjpeg->frame_base_array) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + + sjpeg->frame_base_offset = NULL; + + uint8_t * img_frame_base = data + sjpeg->sjpeg_total_frames * 2; + sjpeg->frame_base_array[0] = img_frame_base; + + for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) { + int offset = *data++; + offset |= *data++ << 8; + sjpeg->frame_base_array[i] = sjpeg->frame_base_array[i - 1] + offset; + } + sjpeg->sjpeg_cache_frame_index = -1; + sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3/*2*/); + if(! sjpeg->frame_cache) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + sjpeg->io.img_cache_buff = sjpeg->frame_cache; + sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; + sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! sjpeg->workb) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + + sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); + if(! sjpeg->tjpeg_jd) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY; + sjpeg->io.lv_file.file_d = NULL; + dsc->img_data = NULL; + return lv_ret; + } + else if(is_jpg(sjpeg->sjpeg_data, raw_sjpeg_data_size) == true) { + + uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! workb_temp) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + io_source_t io_source_temp; + io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY; + io_source_temp.raw_sjpg_data = sjpeg->sjpeg_data; + io_source_temp.raw_sjpg_data_size = sjpeg->sjpeg_data_size; + io_source_temp.raw_sjpg_data_next_read_pos = 0; + + JDEC jd_tmp; + JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); + lv_mem_free(workb_temp); + + + if(rc == JDR_OK) { + sjpeg->sjpeg_x_res = jd_tmp.width; + sjpeg->sjpeg_y_res = jd_tmp.height; + sjpeg->sjpeg_total_frames = 1; + sjpeg->sjpeg_single_frame_height = jd_tmp.height; + + sjpeg->frame_base_array = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); + if(! sjpeg->frame_base_array) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + sjpeg->frame_base_offset = NULL; + + uint8_t * img_frame_base = sjpeg->sjpeg_data; + sjpeg->frame_base_array[0] = img_frame_base; + + sjpeg->sjpeg_cache_frame_index = -1; + sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); + if(! sjpeg->frame_cache) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + + sjpeg->io.img_cache_buff = sjpeg->frame_cache; + sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; + sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! sjpeg->workb) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + + sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); + if(! sjpeg->tjpeg_jd) { + lv_sjpg_cleanup(sjpeg); + sjpeg = NULL; + return LV_RES_INV; + } + + sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY; + sjpeg->io.lv_file.file_d = NULL; + dsc->img_data = NULL; + return lv_ret; + } + else { + lv_ret = LV_RES_INV; + goto end; + } + +end: + lv_mem_free(workb_temp); + + return lv_ret; + } + } + else if(dsc->src_type == LV_IMG_SRC_FILE) { + /* If all fine, then the file will be kept open */ + const char * fn = dsc->src; + uint8_t * data; + + if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) { + + uint8_t buff[22]; + memset(buff, 0, sizeof(buff)); + + + lv_fs_file_t lv_file; + lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + return 78; + } + + + uint32_t rn; + res = lv_fs_read(&lv_file, buff, 22, &rn); + if(res != LV_FS_RES_OK || rn != 22) { + lv_fs_close(&lv_file); + return LV_RES_INV; + } + + if(strcmp((char *)buff, "_SJPG__") == 0) { + + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + if(sjpeg == NULL) { + sjpeg = lv_mem_alloc(sizeof(SJPEG)); + + if(! sjpeg) { + lv_fs_close(&lv_file); + return LV_RES_INV; + } + memset(sjpeg, 0, sizeof(SJPEG)); + + dsc->user_data = sjpeg; + sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; + sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; + } + data = buff; + data += 14; + + sjpeg->sjpeg_x_res = *data++; + sjpeg->sjpeg_x_res |= *data++ << 8; + + sjpeg->sjpeg_y_res = *data++; + sjpeg->sjpeg_y_res |= *data++ << 8; + + sjpeg->sjpeg_total_frames = *data++; + sjpeg->sjpeg_total_frames |= *data++ << 8; + + sjpeg->sjpeg_single_frame_height = *data++; + sjpeg->sjpeg_single_frame_height |= *data++ << 8; + + sjpeg->frame_base_array = NULL;//lv_mem_alloc( sizeof(uint8_t *) * sjpeg->sjpeg_total_frames ); + sjpeg->frame_base_offset = lv_mem_alloc(sizeof(int) * sjpeg->sjpeg_total_frames); + if(! sjpeg->frame_base_offset) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + int img_frame_start_offset = (SJPEG_FRAME_INFO_ARRAY_OFFSET + sjpeg->sjpeg_total_frames * 2); + sjpeg->frame_base_offset[0] = img_frame_start_offset; //pointer used to save integer for now... + + for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) { + res = lv_fs_read(&lv_file, buff, 2, &rn); + if(res != LV_FS_RES_OK || rn != 2) { + lv_fs_close(&lv_file); + return LV_RES_INV; + } + + data = buff; + int offset = *data++; + offset |= *data++ << 8; + sjpeg->frame_base_offset[i] = sjpeg->frame_base_offset[i - 1] + offset; + } + + sjpeg->sjpeg_cache_frame_index = -1; //INVALID AT BEGINNING for a forced compare mismatch at first time. + sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); + if(! sjpeg->frame_cache) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + sjpeg->io.img_cache_buff = sjpeg->frame_cache; + sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; + sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! sjpeg->workb) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); + if(! sjpeg->tjpeg_jd) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + sjpeg->io.type = SJPEG_IO_SOURCE_DISK; + sjpeg->io.lv_file = lv_file; + dsc->img_data = NULL; + return LV_RES_OK; + } + } + else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) { + + lv_fs_file_t lv_file; + lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + return LV_RES_INV; + } + + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + if(sjpeg == NULL) { + sjpeg = lv_mem_alloc(sizeof(SJPEG)); + if(! sjpeg) { + lv_fs_close(&lv_file); + return LV_RES_INV; + } + + memset(sjpeg, 0, sizeof(SJPEG)); + dsc->user_data = sjpeg; + sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; + sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; + } + + uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! workb_temp) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + io_source_t io_source_temp; + io_source_temp.type = SJPEG_IO_SOURCE_DISK; + io_source_temp.raw_sjpg_data_next_read_pos = 0; + io_source_temp.img_cache_buff = NULL; + io_source_temp.lv_file = lv_file; + + JDEC jd_tmp; + + JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); + + lv_mem_free(workb_temp); + + + if(rc == JDR_OK) { + sjpeg->sjpeg_x_res = jd_tmp.width; + sjpeg->sjpeg_y_res = jd_tmp.height; + sjpeg->sjpeg_total_frames = 1; + sjpeg->sjpeg_single_frame_height = jd_tmp.height; + + sjpeg->frame_base_array = NULL; + sjpeg->frame_base_offset = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); + if(! sjpeg->frame_base_offset) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + int img_frame_start_offset = 0; + sjpeg->frame_base_offset[0] = img_frame_start_offset; + + sjpeg->sjpeg_cache_frame_index = -1; + sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); + if(! sjpeg->frame_cache) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + sjpeg->io.img_cache_buff = sjpeg->frame_cache; + sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; + sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); + if(! sjpeg->workb) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); + if(! sjpeg->tjpeg_jd) { + lv_fs_close(&lv_file); + lv_sjpg_cleanup(sjpeg); + return LV_RES_INV; + } + + sjpeg->io.type = SJPEG_IO_SOURCE_DISK; + sjpeg->io.lv_file = lv_file; + dsc->img_data = NULL; + return LV_RES_OK; + + } + else { + if(dsc->user_data) lv_mem_free(dsc->user_data); + lv_fs_close(&lv_file); + return LV_RES_INV; + } + } + } + + return LV_RES_INV; +} + +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't open the whole decoded pixel array. (dsc->img_data == NULL) + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RES_OK: ok; LV_RES_INV: failed + */ + +static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, + lv_coord_t len, uint8_t * buf) +{ + LV_UNUSED(decoder); + if(dsc->src_type == LV_IMG_SRC_VARIABLE) { + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + JRESULT rc; + + int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height; + + /*If line not from cache, refresh cache */ + if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) { + sjpeg->io.raw_sjpg_data = sjpeg->frame_base_array[ sjpeg_req_frame_index ]; + if(sjpeg_req_frame_index == (sjpeg->sjpeg_total_frames - 1)) { + /*This is the last frame. */ + const uint32_t frame_offset = (uint32_t)(sjpeg->io.raw_sjpg_data - sjpeg->sjpeg_data); + sjpeg->io.raw_sjpg_data_size = sjpeg->sjpeg_data_size - frame_offset; + } + else { + sjpeg->io.raw_sjpg_data_size = + (uint32_t)(sjpeg->frame_base_array[sjpeg_req_frame_index + 1] - sjpeg->io.raw_sjpg_data); + } + sjpeg->io.raw_sjpg_data_next_read_pos = 0; + rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io)); + if(rc != JDR_OK) return LV_RES_INV; + rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0); + if(rc != JDR_OK) return LV_RES_INV; + sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index; + } + + int offset = 0; + uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res * + 3; + +#if LV_COLOR_DEPTH == 32 + for(int i = 0; i < len; i++) { + buf[offset + 3] = 0xff; + buf[offset + 2] = *cache++; + buf[offset + 1] = *cache++; + buf[offset + 0] = *cache++; + offset += 4; + } + +#elif LV_COLOR_DEPTH == 16 + + for(int i = 0; i < len; i++) { + uint16_t col_16bit = (*cache++ & 0xf8) << 8; + col_16bit |= (*cache++ & 0xFC) << 3; + col_16bit |= (*cache++ >> 3); +#if LV_BIG_ENDIAN_SYSTEM == 1 || LV_COLOR_16_SWAP == 1 + buf[offset++] = col_16bit >> 8; + buf[offset++] = col_16bit & 0xff; +#else + buf[offset++] = col_16bit & 0xff; + buf[offset++] = col_16bit >> 8; +#endif // LV_BIG_ENDIAN_SYSTEM + } + +#elif LV_COLOR_DEPTH == 8 + + for(int i = 0; i < len; i++) { + uint8_t col_8bit = (*cache++ & 0xC0); + col_8bit |= (*cache++ & 0xe0) >> 2; + col_8bit |= (*cache++ & 0xe0) >> 5; + buf[offset++] = col_8bit; + } +#else +#error Unsupported LV_COLOR_DEPTH + + +#endif // LV_COLOR_DEPTH + return LV_RES_OK; + } + else if(dsc->src_type == LV_IMG_SRC_FILE) { + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + JRESULT rc; + int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height; + + lv_fs_file_t * lv_file_p = &(sjpeg->io.lv_file); + if(!lv_file_p) goto end; + + /*If line not from cache, refresh cache */ + if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) { + sjpeg->io.raw_sjpg_data_next_read_pos = (int)(sjpeg->frame_base_offset [ sjpeg_req_frame_index ]); + lv_fs_seek(&(sjpeg->io.lv_file), sjpeg->io.raw_sjpg_data_next_read_pos, LV_FS_SEEK_SET); + + rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io)); + if(rc != JDR_OK) return LV_RES_INV; + + rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0); + if(rc != JDR_OK) return LV_RES_INV; + + sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index; + } + + int offset = 0; + uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res * + 3; + +#if LV_COLOR_DEPTH == 32 + for(int i = 0; i < len; i++) { + buf[offset + 3] = 0xff; + buf[offset + 2] = *cache++; + buf[offset + 1] = *cache++; + buf[offset + 0] = *cache++; + offset += 4; + } +#elif LV_COLOR_DEPTH == 16 + + for(int i = 0; i < len; i++) { + uint16_t col_8bit = (*cache++ & 0xf8) << 8; + col_8bit |= (*cache++ & 0xFC) << 3; + col_8bit |= (*cache++ >> 3); +#if LV_BIG_ENDIAN_SYSTEM == 1 || LV_COLOR_16_SWAP == 1 + buf[offset++] = col_8bit >> 8; + buf[offset++] = col_8bit & 0xff; +#else + buf[offset++] = col_8bit & 0xff; + buf[offset++] = col_8bit >> 8; +#endif // LV_BIG_ENDIAN_SYSTEM + } + +#elif LV_COLOR_DEPTH == 8 + + for(int i = 0; i < len; i++) { + uint8_t col_8bit = (*cache++ & 0xC0); + col_8bit |= (*cache++ & 0xe0) >> 2; + col_8bit |= (*cache++ & 0xe0) >> 5; + buf[offset++] = col_8bit; + } + +#else +#error Unsupported LV_COLOR_DEPTH + + +#endif // LV_COLOR_DEPTH + + return LV_RES_OK; + } +end: + return LV_RES_INV; +} + +/** + * Free the allocated resources + * @param decoder pointer to the decoder where this function belongs + * @param dsc pointer to a descriptor which describes this decoding session + */ +static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + /*Free all allocated data*/ + SJPEG * sjpeg = (SJPEG *) dsc->user_data; + if(!sjpeg) return; + + switch(dsc->src_type) { + case LV_IMG_SRC_FILE: + if(sjpeg->io.lv_file.file_d) { + lv_fs_close(&(sjpeg->io.lv_file)); + } + lv_sjpg_cleanup(sjpeg); + break; + + case LV_IMG_SRC_VARIABLE: + lv_sjpg_cleanup(sjpeg); + break; + + default: + ; + } +} + +static int is_jpg(const uint8_t * raw_data, size_t len) +{ + const uint8_t jpg_signature[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46}; + if(len < sizeof(jpg_signature)) return false; + return memcmp(jpg_signature, raw_data, sizeof(jpg_signature)) == 0; +} + +static void lv_sjpg_free(SJPEG * sjpeg) +{ + if(sjpeg->frame_cache) lv_mem_free(sjpeg->frame_cache); + if(sjpeg->frame_base_array) lv_mem_free(sjpeg->frame_base_array); + if(sjpeg->frame_base_offset) lv_mem_free(sjpeg->frame_base_offset); + if(sjpeg->tjpeg_jd) lv_mem_free(sjpeg->tjpeg_jd); + if(sjpeg->workb) lv_mem_free(sjpeg->workb); +} + +static void lv_sjpg_cleanup(SJPEG * sjpeg) +{ + if(! sjpeg) return; + + lv_sjpg_free(sjpeg); + lv_mem_free(sjpeg); +} + +#endif /*LV_USE_SJPG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h new file mode 100644 index 000000000..d06e80de5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h @@ -0,0 +1,43 @@ +/** + * @file lv_sjpg.h + * + */ + +#ifndef LV_SJPEG_H +#define LV_SJPEG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#if LV_USE_SJPG + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_split_jpeg_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SJPG*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LV_SJPEG_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c new file mode 100644 index 000000000..47ddefb6e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c @@ -0,0 +1,1155 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021 +/-----------------------------------------------------------------------------/ +/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2021, ChaN, all right reserved. +/ +/ * The TJpgDec module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Oct 04, 2011 R0.01 First release. +/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. +/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. +/ Mar 16, 2019 R0.01c Supprted stdint.h. +/ Jul 01, 2020 R0.01d Fixed wrong integer type usage. +/ May 08, 2021 R0.02 Supprted grayscale image. Separated configuration options. +/ Jun 11, 2021 R0.02a Some performance improvement. +/ Jul 01, 2021 R0.03 Added JD_FASTDECODE option. +/ Some performance improvement. +/----------------------------------------------------------------------------*/ + +#include "tjpgd.h" +#if LV_USE_SJPG + +#if JD_FASTDECODE == 2 +#define HUFF_BIT 10 /* Bit length to apply fast huffman decode */ +#define HUFF_LEN (1 << HUFF_BIT) +#define HUFF_MASK (HUFF_LEN - 1) +#endif + + +/*-----------------------------------------------*/ +/* Zigzag-order to raster-order conversion table */ +/*-----------------------------------------------*/ + +static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + + + +/*-------------------------------------------------*/ +/* Input scale factor of Arai algorithm */ +/* (scaled up 16 bits for fixed point operations) */ +/*-------------------------------------------------*/ + +static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ + (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), + (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), + (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), + (uint16_t)(1.17588*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.38268*8192), (uint16_t)(1.17588*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.32442*8192), + (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), + (uint16_t)(0.78570*8192), (uint16_t)(1.08979*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.61732*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.21677*8192), + (uint16_t)(0.54120*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.29290*8192), (uint16_t)(0.14932*8192), + (uint16_t)(0.27590*8192), (uint16_t)(0.38268*8192), (uint16_t)(0.36048*8192), (uint16_t)(0.32442*8192), (uint16_t)(0.27590*8192), (uint16_t)(0.21678*8192), (uint16_t)(0.14932*8192), (uint16_t)(0.07612*8192) +}; + + + +/*---------------------------------------------*/ +/* Conversion table for fast clipping process */ +/*---------------------------------------------*/ + +#if JD_TBLCLIP + +#define BYTECLIP(v) Clip8[(unsigned int)(v) & 0x3FF] + +static const uint8_t Clip8[1024] = { + /* 0..255 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + /* 256..511 */ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* -512..-257 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* -256..-1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#else /* JD_TBLCLIP */ + +static uint8_t BYTECLIP (int val) +{ + if (val < 0) return 0; + if (val > 255) return 255; + return (uint8_t)val; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Allocate a memory block from memory pool */ +/*-----------------------------------------------------------------------*/ + +static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ + JDEC* jd, /* Pointer to the decompressor object */ + size_t ndata /* Number of bytes to allocate */ +) +{ + char *rp = 0; + + + ndata = (ndata + 3) & ~3; /* Align block size to the word boundary */ + + if (jd->sz_pool >= ndata) { + jd->sz_pool -= ndata; + rp = (char*)jd->pool; /* Get start of available memory pool */ + jd->pool = (void*)(rp + ndata); /* Allocate requierd bytes */ + } + + return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create de-quantization and prescaling tables with a DQT segment */ +/*-----------------------------------------------------------------------*/ + +static JRESULT create_qt_tbl ( /* 0:OK, !0:Failed */ + JDEC* jd, /* Pointer to the decompressor object */ + const uint8_t* data, /* Pointer to the quantizer tables */ + size_t ndata /* Size of input data */ +) +{ + unsigned int i, zi; + uint8_t d; + int32_t *pb; + + + while (ndata) { /* Process all tables in the segment */ + if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ + ndata -= 65; + d = *data++; /* Get table property */ + if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ + i = d & 3; /* Get table ID */ + pb = alloc_pool(jd, 64 * sizeof (int32_t));/* Allocate a memory block for the table */ + if (!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->qttbl[i] = pb; /* Register the table */ + for (i = 0; i < 64; i++) { /* Load the table */ + zi = Zig[i]; /* Zigzag-order to raster-order conversion */ + pb[zi] = (int32_t)((uint32_t)*data++ * Ipsf[zi]); /* Apply scale factor of Arai algorithm to the de-quantizers */ + } + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create huffman code tables with a DHT segment */ +/*-----------------------------------------------------------------------*/ + +static JRESULT create_huffman_tbl ( /* 0:OK, !0:Failed */ + JDEC* jd, /* Pointer to the decompressor object */ + const uint8_t* data, /* Pointer to the packed huffman tables */ + size_t ndata /* Size of input data */ +) +{ + unsigned int i, j, b, cls, num; + size_t np; + uint8_t d, *pb, *pd; + uint16_t hc, *ph; + + + while (ndata) { /* Process all tables in the segment */ + if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ + ndata -= 17; + d = *data++; /* Get table number and class */ + if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ + cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ + pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ + if (!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->huffbits[num][cls] = pb; + for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ + np += (pb[i] = *data++); /* Get sum of code words for each code */ + } + ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */ + if (!ph) return JDR_MEM1; /* Err: not enough memory */ + jd->huffcode[num][cls] = ph; + hc = 0; + for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ + b = pb[i]; + while (b--) ph[j++] = hc++; + hc <<= 1; + } + + if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ + ndata -= np; + pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ + if (!pd) return JDR_MEM1; /* Err: not enough memory */ + jd->huffdata[num][cls] = pd; + for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code word */ + d = *data++; + if (!cls && d > 11) return JDR_FMT1; + pd[i] = d; + } +#if JD_FASTDECODE == 2 + { /* Create fast huffman decode table */ + unsigned int span, td, ti; + uint16_t *tbl_ac = 0; + uint8_t *tbl_dc = 0; + + if (cls) { + tbl_ac = alloc_pool(jd, HUFF_LEN * sizeof (uint16_t)); /* LUT for AC elements */ + if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */ + jd->hufflut_ac[num] = tbl_ac; + memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */ + } else { + tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */ + if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */ + jd->hufflut_dc[num] = tbl_dc; + memset(tbl_dc, 0xFF, HUFF_LEN * sizeof (uint8_t)); /* Default value (0xFF: may be long code) */ + } + for (i = b = 0; b < HUFF_BIT; b++) { /* Create LUT */ + for (j = pb[b]; j; j--) { + ti = ph[i] << (HUFF_BIT - 1 - b) & HUFF_MASK; /* Index of input pattern for the code */ + if (cls) { + td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */ + for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ; + } else { + td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */ + for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ; + } + } + } + jd->longofs[num][cls] = i; /* Code table offset for long code */ + } +#endif + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract a huffman decoded data from input stream */ +/*-----------------------------------------------------------------------*/ + +static int huffext ( /* >=0: decoded data, <0: error code */ + JDEC* jd, /* Pointer to the decompressor object */ + unsigned int id, /* Table ID (0:Y, 1:C) */ + unsigned int cls /* Table class (0:DC, 1:AC) */ +) +{ + size_t dc = jd->dctr; + uint8_t *dp = jd->dptr; + unsigned int d, flg = 0; + +#if JD_FASTDECODE == 0 + uint8_t bm, nd, bl; + const uint8_t *hb = jd->huffbits[id][cls]; /* Bit distribution table */ + const uint16_t *hc = jd->huffcode[id][cls]; /* Code word table */ + const uint8_t *hd = jd->huffdata[id][cls]; /* Data table */ + + + bm = jd->dbit; /* Bit mask to extract */ + d = 0; bl = 16; /* Max code length */ + do { + if (!bm) { /* Next byte? */ + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if (flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = 0xFF; /* The flag is a data 0xFF */ + } else { + if (*dp == 0xFF) { /* Is start of flag sequence? */ + flg = 1; continue; /* Enter flag sequence, get trailing byte */ + } + } + bm = 0x80; /* Read from MSB */ + } + d <<= 1; /* Get a bit */ + if (*dp & bm) d++; + bm >>= 1; + + for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */ + if (d == *hc++) { /* Matched? */ + jd->dbit = bm; jd->dctr = dc; jd->dptr = dp; + return *hd; /* Return the decoded data */ + } + hd++; + } + bl--; + } while (bl); + +#else + const uint8_t *hb, *hd; + const uint16_t *hc; + unsigned int nc, bl, wbit = jd->dbit % 32; + uint32_t w = jd->wreg & ((1UL << wbit) - 1); + + + while (wbit < 16) { /* Prepare 16 bits into the working register */ + if (jd->marker) { + d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */ + } else { + if (!dc) { /* Buffer empty, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + d = *dp++; dc--; + if (flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ + d = 0xFF; + } else { + if (d == 0xFF) { /* Is start of flag sequence? */ + flg = 1; continue; /* Enter flag sequence, get trailing byte */ + } + } + } + w = w << 8 | d; /* Shift 8 bits in the working register */ + wbit += 8; + } + jd->dctr = dc; jd->dptr = dp; + jd->wreg = w; + +#if JD_FASTDECODE == 2 + /* Table serch for the short codes */ + d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */ + if (cls) { /* AC element */ + d = jd->hufflut_ac[id][d]; /* Table decode */ + if (d != 0xFFFF) { /* It is done if hit in short code */ + jd->dbit = wbit - (d >> 8); /* Snip the code length */ + return d & 0xFF; /* b7..0: zero run and following data bits */ + } + } else { /* DC element */ + d = jd->hufflut_dc[id][d]; /* Table decode */ + if (d != 0xFF) { /* It is done if hit in short code */ + jd->dbit = wbit - (d >> 4); /* Snip the code length */ + return d & 0xF; /* b3..0: following data bits */ + } + } + + /* Incremental serch for the codes longer than HUFF_BIT */ + hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */ + hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */ + hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */ + bl = HUFF_BIT + 1; +#else + /* Incremental serch for all codes */ + hb = jd->huffbits[id][cls]; /* Bit distribution table */ + hc = jd->huffcode[id][cls]; /* Code word table */ + hd = jd->huffdata[id][cls]; /* Data table */ + bl = 1; +#endif + for ( ; bl <= 16; bl++) { /* Incremental search */ + nc = *hb++; + if (nc) { + d = w >> (wbit - bl); + do { /* Search the code word in this bit length */ + if (d == *hc++) { /* Matched? */ + jd->dbit = wbit - bl; /* Snip the huffman code */ + return *hd; /* Return the decoded data */ + } + hd++; + } while (--nc); + } + } +#endif + + return 0 - (int)JDR_FMT1; /* Err: code not found (may be collapted data) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract N bits from input stream */ +/*-----------------------------------------------------------------------*/ + +static int bitext ( /* >=0: extracted data, <0: error code */ + JDEC* jd, /* Pointer to the decompressor object */ + unsigned int nbit /* Number of bits to extract (1 to 16) */ +) +{ + size_t dc = jd->dctr; + uint8_t *dp = jd->dptr; + unsigned int d, flg = 0; + +#if JD_FASTDECODE == 0 + uint8_t mbit = jd->dbit; + + d = 0; + do { + if (!mbit) { /* Next byte? */ + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if (flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = 0xFF; /* The flag is a data 0xFF */ + } else { + if (*dp == 0xFF) { /* Is start of flag sequence? */ + flg = 1; continue; /* Enter flag sequence */ + } + } + mbit = 0x80; /* Read from MSB */ + } + d <<= 1; /* Get a bit */ + if (*dp & mbit) d |= 1; + mbit >>= 1; + nbit--; + } while (nbit); + + jd->dbit = mbit; jd->dctr = dc; jd->dptr = dp; + return (int)d; + +#else + unsigned int wbit = jd->dbit % 32; + uint32_t w = jd->wreg & ((1UL << wbit) - 1); + + + while (wbit < nbit) { /* Prepare nbit bits into the working register */ + if (jd->marker) { + d = 0xFF; /* Input stream stalled, generate stuff bits */ + } else { + if (!dc) { /* Buffer empty, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + d = *dp++; dc--; + if (flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ + d = 0xFF; + } else { + if (d == 0xFF) { /* Is start of flag sequence? */ + flg = 1; continue; /* Enter flag sequence, get trailing byte */ + } + } + } + w = w << 8 | d; /* Get 8 bits into the working register */ + wbit += 8; + } + jd->wreg = w; jd->dbit = wbit - nbit; + jd->dctr = dc; jd->dptr = dp; + + return (int)(w >> ((wbit - nbit) % 32)); +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Process restart interval */ +/*-----------------------------------------------------------------------*/ + +static JRESULT restart ( + JDEC* jd, /* Pointer to the decompressor object */ + uint16_t rstn /* Expected restert sequense number */ +) +{ + unsigned int i; + uint8_t *dp = jd->dptr; + size_t dc = jd->dctr; + +#if JD_FASTDECODE == 0 + uint16_t d = 0; + + /* Get two bytes from the input stream */ + for (i = 0; i < 2; i++) { + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return JDR_INP; + } else { + dp++; + } + dc--; + d = d << 8 | *dp; /* Get a byte */ + } + jd->dptr = dp; jd->dctr = dc; jd->dbit = 0; + + /* Check the marker */ + if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { + return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ + } + +#else + uint16_t marker; + + + if (jd->marker) { /* Generate a maker if it has been detected */ + marker = 0xFF00 | jd->marker; + jd->marker = 0; + } else { + marker = 0; + for (i = 0; i < 2; i++) { /* Get a restart marker */ + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return JDR_INP; + } + marker = (marker << 8) | *dp++; /* Get a byte */ + dc--; + } + jd->dptr = dp; jd->dctr = dc; + } + + /* Check the marker */ + if ((marker & 0xFFD8) != 0xFFD0 || (marker & 7) != (rstn & 7)) { + return JDR_FMT1; /* Err: expected RSTn marker was not detected (may be collapted data) */ + } + + jd->dbit = 0; /* Discard stuff bits */ +#endif + + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Reset DC offset */ + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ +/*-----------------------------------------------------------------------*/ + +static void block_idct ( + int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ + jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */ +) +{ + const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); + int32_t v0, v1, v2, v3, v4, v5, v6, v7; + int32_t t10, t11, t12, t13; + int i; + + /* Process columns */ + for (i = 0; i < 8; i++) { + v0 = src[8 * 0]; /* Get even elements */ + v1 = src[8 * 2]; + v2 = src[8 * 4]; + v3 = src[8 * 6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[8 * 7]; /* Get odd elements */ + v5 = src[8 * 1]; + v6 = src[8 * 5]; + v7 = src[8 * 3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + src[8 * 0] = v0 + v7; /* Write-back transformed values */ + src[8 * 7] = v0 - v7; + src[8 * 1] = v1 + v6; + src[8 * 6] = v1 - v6; + src[8 * 2] = v2 + v5; + src[8 * 5] = v2 - v5; + src[8 * 3] = v3 + v4; + src[8 * 4] = v3 - v4; + + src++; /* Next column */ + } + + /* Process rows */ + src -= 8; + for (i = 0; i < 8; i++) { + v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ + v1 = src[2]; + v2 = src[4]; + v3 = src[6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[7]; /* Get odd elements */ + v5 = src[1]; + v6 = src[5]; + v7 = src[3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + /* Descale the transformed values 8 bits and output a row */ +#if JD_FASTDECODE >= 1 + dst[0] = (int16_t)((v0 + v7) >> 8); + dst[7] = (int16_t)((v0 - v7) >> 8); + dst[1] = (int16_t)((v1 + v6) >> 8); + dst[6] = (int16_t)((v1 - v6) >> 8); + dst[2] = (int16_t)((v2 + v5) >> 8); + dst[5] = (int16_t)((v2 - v5) >> 8); + dst[3] = (int16_t)((v3 + v4) >> 8); + dst[4] = (int16_t)((v3 - v4) >> 8); +#else + dst[0] = BYTECLIP((v0 + v7) >> 8); + dst[7] = BYTECLIP((v0 - v7) >> 8); + dst[1] = BYTECLIP((v1 + v6) >> 8); + dst[6] = BYTECLIP((v1 - v6) >> 8); + dst[2] = BYTECLIP((v2 + v5) >> 8); + dst[5] = BYTECLIP((v2 - v5) >> 8); + dst[3] = BYTECLIP((v3 + v4) >> 8); + dst[4] = BYTECLIP((v3 - v4) >> 8); +#endif + + dst += 8; src += 8; /* Next row */ + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load all blocks in an MCU into working buffer */ +/*-----------------------------------------------------------------------*/ + +static JRESULT mcu_load ( + JDEC* jd /* Pointer to the decompressor object */ +) +{ + int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ + int d, e; + unsigned int blk, nby, i, bc, z, id, cmp; + jd_yuv_t *bp; + const int32_t *dqf; + + + nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ + bp = jd->mcubuf; /* Pointer to the first block of MCU */ + + for (blk = 0; blk < nby + 2; blk++) { /* Get nby Y blocks and two C blocks */ + cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ + + if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */ + for (i = 0; i < 64; bp[i++] = 128) ; + + } else { /* Load Y/C blocks from input stream */ + id = cmp ? 1 : 0; /* Huffman table ID of this component */ + + /* Extract a DC element from input stream */ + d = huffext(jd, id, 0); /* Extract a huffman coded data (bit length) */ + if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input */ + bc = (unsigned int)d; + d = jd->dcv[cmp]; /* DC value of previous block */ + if (bc) { /* If there is any difference from previous block */ + e = bitext(jd, bc); /* Extract data bits */ + if (e < 0) return (JRESULT)(0 - e); /* Err: input */ + bc = 1 << (bc - 1); /* MSB position */ + if (!(e & bc)) e -= (bc << 1) - 1; /* Restore negative value if needed */ + d += e; /* Get current value */ + jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */ + } + dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ + tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + + /* Extract following 63 AC elements from input stream */ + memset(&tmp[1], 0, 63 * sizeof (int32_t)); /* Initialize all AC elements */ + z = 1; /* Top of the AC elements (in zigzag-order) */ + do { + d = huffext(jd, id, 1); /* Extract a huffman coded value (zero runs and bit length) */ + if (d == 0) break; /* EOB? */ + if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input error */ + bc = (unsigned int)d; + z += bc >> 4; /* Skip leading zero run */ + if (z >= 64) return JDR_FMT1; /* Too long zero run */ + if (bc &= 0x0F) { /* Bit length? */ + d = bitext(jd, bc); /* Extract data bits */ + if (d < 0) return (JRESULT)(0 - d); /* Err: input device */ + bc = 1 << (bc - 1); /* MSB position */ + if (!(d & bc)) d -= (bc << 1) - 1; /* Restore negative value if needed */ + i = Zig[z]; /* Get raster-order index */ + tmp[i] = d * dqf[i] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + } + } while (++z < 64); /* Next AC element */ + + if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */ + if (z == 1 || (JD_USE_SCALE && jd->scale == 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be ommited and the block is filled with DC value */ + d = (jd_yuv_t)((*tmp / 256) + 128); + if (JD_FASTDECODE >= 1) { + for (i = 0; i < 64; bp[i++] = d) ; + } else { + memset(bp, d, 64); + } + } else { + block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ + } + } + } + + bp += 64; /* Next block */ + } + + return JDR_OK; /* All blocks have been loaded successfully */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ +/*-----------------------------------------------------------------------*/ + +static JRESULT mcu_output ( + JDEC* jd, /* Pointer to the decompressor object */ + int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ + unsigned int img_x, /* MCU location in the image */ + unsigned int img_y /* MCU location in the image */ +) +{ + const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */ + unsigned int ix, iy, mx, my, rx, ry; + int yy, cb, cr; + jd_yuv_t *py, *pc; + uint8_t *pix; + JRECT rect; + + + mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ + rx = (img_x + mx <= jd->width) ? mx : jd->width - img_x; /* Output rectangular size (it may be clipped at right/bottom end of image) */ + ry = (img_y + my <= jd->height) ? my : jd->height - img_y; + if (JD_USE_SCALE) { + rx >>= jd->scale; ry >>= jd->scale; + if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ + img_x >>= jd->scale; img_y >>= jd->scale; + } + rect.left = img_x; rect.right = img_x + rx - 1; /* Rectangular area in the frame buffer */ + rect.top = img_y; rect.bottom = img_y + ry - 1; + + + if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ + pix = (uint8_t*)jd->workbuf; + + if (JD_FORMAT != 2) { /* RGB output (build an RGB MCU from Y/C component) */ + for (iy = 0; iy < my; iy++) { + pc = py = jd->mcubuf; + if (my == 16) { /* Double block height? */ + pc += 64 * 4 + (iy >> 1) * 8; + if (iy >= 8) py += 64; + } else { /* Single block height */ + pc += mx * 8 + iy * 8; + } + py += iy * 8; + for (ix = 0; ix < mx; ix++) { + cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */ + cr = pc[64] - 128; + if (mx == 16) { /* Double block width? */ + if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ + pc += ix & 1; /* Step forward chroma pointer every two pixels */ + } else { /* Single block width */ + pc++; /* Step forward chroma pointer every pixel */ + } + yy = *py++; /* Get Y component */ + *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC); + *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); + *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC); + } + } + } else { /* Monochrome output (build a grayscale MCU from Y comopnent) */ + for (iy = 0; iy < my; iy++) { + py = jd->mcubuf + iy * 8; + if (my == 16) { /* Double block height? */ + if (iy >= 8) py += 64; + } + for (ix = 0; ix < mx; ix++) { + if (mx == 16) { /* Double block width? */ + if (ix == 8) py += 64 - 8; /* Jump to next block if double block height */ + } + *pix++ = (uint8_t)*py++; /* Get and store a Y value as grayscale */ + } + } + } + + /* Descale the MCU rectangular if needed */ + if (JD_USE_SCALE && jd->scale) { + unsigned int x, y, r, g, b, s, w, a; + uint8_t *op; + + /* Get averaged RGB value of each square correcponds to a pixel */ + s = jd->scale * 2; /* Number of shifts for averaging */ + w = 1 << jd->scale; /* Width of square */ + a = (mx - w) * (JD_FORMAT != 2 ? 3 : 1); /* Bytes to skip for next line in the square */ + op = (uint8_t*)jd->workbuf; + for (iy = 0; iy < my; iy += w) { + for (ix = 0; ix < mx; ix += w) { + pix = (uint8_t*)jd->workbuf + (iy * mx + ix) * (JD_FORMAT != 2 ? 3 : 1); + r = g = b = 0; + for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ + for (x = 0; x < w; x++) { + r += *pix++; /* Accumulate R or Y (monochrome output) */ + if (JD_FORMAT != 2) { /* RGB output? */ + g += *pix++; /* Accumulate G */ + b += *pix++; /* Accumulate B */ + } + } + pix += a; + } /* Put the averaged pixel value */ + *op++ = (uint8_t)(r >> s); /* Put R or Y (monochrome output) */ + if (JD_FORMAT != 2) { /* RGB output? */ + *op++ = (uint8_t)(g >> s); /* Put G */ + *op++ = (uint8_t)(b >> s); /* Put B */ + } + } + } + } + + } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ + + /* Build a 1/8 descaled RGB MCU from discrete comopnents */ + pix = (uint8_t*)jd->workbuf; + pc = jd->mcubuf + mx * my; + cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ + cr = pc[64] - 128; + for (iy = 0; iy < my; iy += 8) { + py = jd->mcubuf; + if (iy == 8) py += 64 * 2; + for (ix = 0; ix < mx; ix += 8) { + yy = *py; /* Get Y component */ + py += 64; + if (JD_FORMAT != 2) { + *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr / CVACC)); + *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); + *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb / CVACC)); + } else { + *pix++ = yy; + } + } + } + } + + /* Squeeze up pixel table if a part of MCU is to be truncated */ + mx >>= jd->scale; + if (rx < mx) { /* Is the MCU spans rigit edge? */ + uint8_t *s, *d; + unsigned int x, y; + + s = d = (uint8_t*)jd->workbuf; + for (y = 0; y < ry; y++) { + for (x = 0; x < rx; x++) { /* Copy effective pixels */ + *d++ = *s++; + if (JD_FORMAT != 2) { + *d++ = *s++; + *d++ = *s++; + } + } + s += (mx - rx) * (JD_FORMAT != 2 ? 3 : 1); /* Skip truncated pixels */ + } + } + + /* Convert RGB888 to RGB565 if needed */ + if (JD_FORMAT == 1) { + uint8_t *s = (uint8_t*)jd->workbuf; + uint16_t w, *d = (uint16_t*)s; + unsigned int n = rx * ry; + + do { + w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ + w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ + w |= *s++ >> 3; /* -----------BBBBB */ + *d++ = w; + } while (--n); + } + + /* Output the rectangular */ + return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Analyze the JPEG image and Initialize decompressor object */ +/*-----------------------------------------------------------------------*/ + +#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) + + +JRESULT jd_prepare ( + JDEC* jd, /* Blank decompressor object */ + size_t (*infunc)(JDEC*, uint8_t*, size_t), /* JPEG strem input function */ + void* pool, /* Working buffer for the decompression session */ + size_t sz_pool, /* Size of working buffer */ + void* dev /* I/O device identifier for the session */ +) +{ + uint8_t *seg, b; + uint16_t marker; + unsigned int n, i, ofs; + size_t len; + JRESULT rc; + + + memset(jd, 0, sizeof (JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */ + jd->pool = pool; /* Work memroy */ + jd->sz_pool = sz_pool; /* Size of given work memory */ + jd->infunc = infunc; /* Stream input function */ + jd->device = dev; /* I/O device identifier */ + + jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ + if (!seg) return JDR_MEM1; + + ofs = marker = 0; /* Find SOI marker */ + do { + if (jd->infunc(jd, seg, 1) != 1) return JDR_INP; /* Err: SOI was not detected */ + ofs++; + marker = marker << 8 | seg[0]; + } while (marker != 0xFFD8); + + for (;;) { /* Parse JPEG segments */ + /* Get a JPEG marker */ + if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; + marker = LDB_WORD(seg); /* Marker */ + len = LDB_WORD(seg + 2); /* Length field */ + if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; + len -= 2; /* Segent content size */ + ofs += 4 + len; /* Number of bytes loaded */ + + switch (marker & 0xFF) { + case 0xC0: /* SOF0 (baseline JPEG) */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + jd->width = LDB_WORD(&seg[3]); /* Image width in unit of pixel */ + jd->height = LDB_WORD(&seg[1]); /* Image height in unit of pixel */ + jd->ncomp = seg[5]; /* Number of color components */ + if (jd->ncomp != 3 && jd->ncomp != 1) return JDR_FMT3; /* Err: Supports only Grayscale and Y/Cb/Cr */ + + /* Check each image component */ + for (i = 0; i < jd->ncomp; i++) { + b = seg[7 + 3 * i]; /* Get sampling factor */ + if (i == 0) { /* Y component */ + if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ + return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ + } + jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ + } else { /* Cb/Cr component */ + if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */ + } + jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ + if (jd->qtid[i] > 3) return JDR_FMT3; /* Err: Invalid ID */ + } + break; + + case 0xDD: /* DRI - Define Restart Interval */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + jd->nrst = LDB_WORD(seg); /* Get restart interval (MCUs) */ + break; + + case 0xC4: /* DHT - Define Huffman Tables */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + rc = create_huffman_tbl(jd, seg, len); /* Create huffman tables */ + if (rc) return rc; + break; + + case 0xDB: /* DQT - Define Quaitizer Tables */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + rc = create_qt_tbl(jd, seg, len); /* Create de-quantizer tables */ + if (rc) return rc; + break; + + case 0xDA: /* SOS - Start of Scan */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ + if (seg[0] != jd->ncomp) return JDR_FMT3; /* Err: Wrong color components */ + + /* Check if all tables corresponding to each components have been loaded */ + for (i = 0; i < jd->ncomp; i++) { + b = seg[2 + 2 * i]; /* Get huffman table ID */ + if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ + n = i ? 1 : 0; /* Component class */ + if (!jd->huffbits[n][0] || !jd->huffbits[n][1]) { /* Check huffman table for this component */ + return JDR_FMT1; /* Err: Nnot loaded */ + } + if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ + return JDR_FMT1; /* Err: Not loaded */ + } + } + + /* Allocate working buffer for MCU and pixel output */ + n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ + if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ + len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ + if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ + jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ + if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ + jd->mcubuf = alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t)); /* Allocate MCU working buffer */ + if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ + + /* Align stream read offset to JD_SZBUF */ + if (ofs %= JD_SZBUF) { + jd->dctr = jd->infunc(jd, seg + ofs, (size_t)(JD_SZBUF - ofs)); + } + jd->dptr = seg + ofs - (JD_FASTDECODE ? 0 : 1); + + return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ + + case 0xC1: /* SOF1 */ + case 0xC2: /* SOF2 */ + case 0xC3: /* SOF3 */ + case 0xC5: /* SOF5 */ + case 0xC6: /* SOF6 */ + case 0xC7: /* SOF7 */ + case 0xC9: /* SOF9 */ + case 0xCA: /* SOF10 */ + case 0xCB: /* SOF11 */ + case 0xCD: /* SOF13 */ + case 0xCE: /* SOF14 */ + case 0xCF: /* SOF15 */ + case 0xD9: /* EOI */ + return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ + + default: /* Unknown segment (comment, exif or etc..) */ + /* Skip segment data (null pointer specifies to remove data from the stream) */ + if (jd->infunc(jd, 0, len) != len) return JDR_INP; + } + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Start to decompress the JPEG picture */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_decomp ( + JDEC* jd, /* Initialized decompression object */ + int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ + uint8_t scale /* Output de-scaling factor (0 to 3) */ +) +{ + unsigned int x, y, mx, my; + uint16_t rst, rsc; + JRESULT rc; + + + if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; + jd->scale = scale; + + mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ + + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ + rst = rsc = 0; + + rc = JDR_OK; + for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ + for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ + if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ + rc = restart(jd, rsc++); + if (rc != JDR_OK) return rc; + rst = 1; + } + rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ + if (rc != JDR_OK) return rc; + rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */ + if (rc != JDR_OK) return rc; + } + } + + return rc; +} + +#endif /*LV_USE_SJPG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h new file mode 100644 index 000000000..b255ccfcf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h @@ -0,0 +1,93 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 +/----------------------------------------------------------------------------*/ +#ifndef DEF_TJPGDEC +#define DEF_TJPGDEC + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../lv_conf_internal.h" +#if LV_USE_SJPG + +#include "tjpgdcnf.h" +#include +#include + +#if JD_FASTDECODE >= 1 +typedef int16_t jd_yuv_t; +#else +typedef uint8_t jd_yuv_t; +#endif + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be broken data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + +/* Rectangular region in the output image */ +typedef struct { + uint16_t left; /* Left end */ + uint16_t right; /* Right end */ + uint16_t top; /* Top end */ + uint16_t bottom; /* Bottom end */ +} JRECT; + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + size_t dctr; /* Number of bytes available in the input buffer */ + uint8_t* dptr; /* Current data read ptr */ + uint8_t* inbuf; /* Bit stream input buffer */ + uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */ + uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ + int16_t dcv[3]; /* Previous DC element of each component */ + uint16_t nrst; /* Restart inverval */ + uint16_t width, height; /* Size of the input image (pixel) */ + uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + int32_t* qttbl[4]; /* Dequantizer tables [id] */ +#if JD_FASTDECODE >= 1 + uint32_t wreg; /* Working shift register */ + uint8_t marker; /* Detected marker (0:None) */ +#if JD_FASTDECODE == 2 + uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */ + uint16_t* hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */ + uint8_t* hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */ +#endif +#endif + void* workbuf; /* Working buffer for IDCT and RGB output */ + jd_yuv_t* mcubuf; /* Working buffer for the MCU */ + void* pool; /* Pointer to available memory pool */ + size_t sz_pool; /* Size of momory pool (bytes available) */ + size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */ + void* device; /* Pointer to I/O device identifiler for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare (JDEC* jd, size_t (*infunc)(JDEC*,uint8_t*,size_t), void* pool, size_t sz_pool, void* dev); +JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale); + +#endif /*LV_USE_SJPG*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h new file mode 100644 index 000000000..6d425e6f1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h @@ -0,0 +1,33 @@ +/*----------------------------------------------*/ +/* TJpgDec System Configurations R0.03 */ +/*----------------------------------------------*/ + +#define JD_SZBUF 512 +/* Specifies size of stream input buffer */ + +#define JD_FORMAT 0 +/* Specifies output pixel format. +/ 0: RGB888 (24-bit/pix) +/ 1: RGB565 (16-bit/pix) +/ 2: Grayscale (8-bit/pix) +*/ + +#define JD_USE_SCALE 1 +/* Switches output descaling feature. +/ 0: Disable +/ 1: Enable +*/ + +#define JD_TBLCLIP 1 +/* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size. +/ 0: Disable +/ 1: Enable +*/ + +#define JD_FASTDECODE 0 +/* Optimization level +/ 0: Basic optimization. Suitable for 8/16-bit MCUs. +/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. +/ 2: + Table conversion for huffman decoding (wants 6 << HUFF_BIT bytes of RAM) +*/ + diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c index b6ed79544..e7c604103 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c @@ -42,6 +42,10 @@ void lv_extra_init(void) lv_grid_init(); #endif +#if LV_USE_MSG + lv_msg_init(); +#endif + #if LV_USE_FS_FATFS != '\0' lv_fs_fatfs_init(); #endif @@ -58,6 +62,10 @@ void lv_extra_init(void) lv_fs_win32_init(); #endif +#if LV_USE_FFMPEG + lv_ffmpeg_init(); +#endif + #if LV_USE_PNG lv_png_init(); #endif @@ -71,6 +79,7 @@ void lv_extra_init(void) #endif // TASMOTA Specific, the initialization is done in Tasmota code to adjust with PSRAM + // #if LV_USE_FREETYPE // /*Init freetype library*/ // # if LV_FREETYPE_CACHE_SIZE >= 0 @@ -79,10 +88,6 @@ void lv_extra_init(void) // lv_freetype_init(0, 0, 0); // # endif // #endif - -#if LV_USE_FFMPEG - lv_ffmpeg_init(); -#endif } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h index ea9ce381b..c0306a980 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h @@ -14,6 +14,12 @@ extern "C" { * INCLUDES *********************/ +#include "layouts/lv_layouts.h" +#include "libs/lv_libs.h" +#include "others/lv_others.h" +#include "themes/lv_themes.h" +#include "widgets/lv_widgets.h" + /********************* * DEFINES *********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/extra.mk b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk similarity index 100% rename from lib/libesp32_lvgl/lvgl/src/extra/extra.mk rename to lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/README.md b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c new file mode 100644 index 000000000..a2cdfadc2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c @@ -0,0 +1,144 @@ +/** + * @file lv_fragment.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_fragment.h" + +#if LV_USE_FRAGMENT + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void cb_delete_assertion(lv_event_t * event); + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args) +{ + LV_ASSERT_NULL(cls); + LV_ASSERT_NULL(cls->create_obj_cb); + LV_ASSERT(cls->instance_size > 0); + lv_fragment_t * instance = lv_mem_alloc(cls->instance_size); + lv_memset_00(instance, cls->instance_size); + instance->cls = cls; + instance->child_manager = lv_fragment_manager_create(instance); + if(cls->constructor_cb) { + cls->constructor_cb(instance, args); + } + return instance; +} + +void lv_fragment_del(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + if(fragment->managed) { + lv_fragment_manager_remove(fragment->managed->manager, fragment); + return; + } + if(fragment->obj) { + lv_fragment_del_obj(fragment); + } + /* Objects will leak if this function called before objects deleted */ + const lv_fragment_class_t * cls = fragment->cls; + if(cls->destructor_cb) { + cls->destructor_cb(fragment); + } + lv_fragment_manager_del(fragment->child_manager); + lv_mem_free(fragment); +} + +lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + LV_ASSERT_NULL(fragment->managed); + return fragment->managed->manager; +} + +lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + LV_ASSERT_NULL(fragment->managed); + return fragment->managed->container; +} + +lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + LV_ASSERT_NULL(fragment->managed); + return lv_fragment_manager_get_parent_fragment(fragment->managed->manager); +} + +lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container) +{ + lv_fragment_managed_states_t * states = fragment->managed; + if(states) { + states->destroying_obj = false; + } + const lv_fragment_class_t * cls = fragment->cls; + lv_obj_t * obj = cls->create_obj_cb(fragment, container); + LV_ASSERT_NULL(obj); + fragment->obj = obj; + lv_fragment_manager_create_obj(fragment->child_manager); + if(states) { + states->obj_created = true; + lv_obj_add_event_cb(obj, cb_delete_assertion, LV_EVENT_DELETE, NULL); + } + if(cls->obj_created_cb) { + cls->obj_created_cb(fragment, obj); + } + return obj; +} + +void lv_fragment_del_obj(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + lv_fragment_manager_del_obj(fragment->child_manager); + lv_fragment_managed_states_t * states = fragment->managed; + if(states) { + if(!states->obj_created) return; + states->destroying_obj = true; + bool cb_removed = lv_obj_remove_event_cb(fragment->obj, cb_delete_assertion); + LV_ASSERT(cb_removed); + } + LV_ASSERT_NULL(fragment->obj); + const lv_fragment_class_t * cls = fragment->cls; + if(cls->obj_will_delete_cb) { + cls->obj_will_delete_cb(fragment, fragment->obj); + } + lv_obj_del(fragment->obj); + if(cls->obj_deleted_cb) { + cls->obj_deleted_cb(fragment, fragment->obj); + } + if(states) { + states->obj_created = false; + } + fragment->obj = NULL; +} + +void lv_fragment_recreate_obj(lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(fragment); + LV_ASSERT_NULL(fragment->managed); + lv_fragment_del_obj(fragment); + lv_fragment_create_obj(fragment, *fragment->managed->container); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void cb_delete_assertion(lv_event_t * event) +{ + LV_UNUSED(event); + LV_ASSERT_MSG(0, "Please delete objects with lv_fragment_destroy_obj"); +} + +#endif /*LV_USE_FRAGMENT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h new file mode 100644 index 000000000..da30b39a5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h @@ -0,0 +1,339 @@ +/** + * Public header for Fragment + * @file lv_fragment.h + */ + +#ifndef LV_FRAGMENT_H +#define LV_FRAGMENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_FRAGMENT + +#include "../../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_fragment_manager_t lv_fragment_manager_t; + +typedef struct _lv_fragment_t lv_fragment_t; +typedef struct _lv_fragment_class_t lv_fragment_class_t; +typedef struct _lv_fragment_managed_states_t lv_fragment_managed_states_t; + +struct _lv_fragment_t { + /** + * Class of this fragment + */ + const lv_fragment_class_t * cls; + /** + * Managed fragment states. If not null, then this fragment is managed. + * + * @warning Don't modify values inside this struct! + */ + lv_fragment_managed_states_t * managed; + /** + * Child fragment manager + */ + lv_fragment_manager_t * child_manager; + /** + * lv_obj returned by create_obj_cb + */ + lv_obj_t * obj; + +}; + +struct _lv_fragment_class_t { + /** + * Constructor function for fragment class + * @param self Fragment instance + * @param args Arguments assigned by fragment manager + */ + void (*constructor_cb)(lv_fragment_t * self, void * args); + + /** + * Destructor function for fragment class + * @param self Fragment instance, will be freed after this call + */ + void (*destructor_cb)(lv_fragment_t * self); + + /** + * Fragment attached to manager + * @param self Fragment instance + */ + void (*attached_cb)(lv_fragment_t * self); + + /** + * Fragment detached from manager + * @param self Fragment instance + */ + void (*detached_cb)(lv_fragment_t * self); + + /** + * Create objects + * @param self Fragment instance + * @param container Container of the objects should be created upon + * @return Created object, NULL if multiple objects has been created + */ + lv_obj_t * (*create_obj_cb)(lv_fragment_t * self, lv_obj_t * container); + + /** + * + * @param self Fragment instance + * @param obj lv_obj returned by create_obj_cb + */ + void (*obj_created_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Called before objects in the fragment will be deleted. + * + * @param self Fragment instance + * @param obj object with this fragment + */ + void (*obj_will_delete_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Called when the object created by fragment received `LV_EVENT_DELETE` event + * @param self Fragment instance + * @param obj object with this fragment + */ + void (*obj_deleted_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Handle event + * @param self Fragment instance + * @param which User-defined ID of event + * @param data1 User-defined data + * @param data2 User-defined data + */ + bool (*event_cb)(lv_fragment_t * self, int code, void * userdata); + + /** + * *REQUIRED*: Allocation size of fragment + */ + size_t instance_size; +}; + +/** + * Fragment states + */ +typedef struct _lv_fragment_managed_states_t { + /** + * Class of the fragment + */ + const lv_fragment_class_t * cls; + /** + * Manager the fragment attached to + */ + lv_fragment_manager_t * manager; + /** + * Container object the fragment adding view to + */ + lv_obj_t * const * container; + /** + * Fragment instance + */ + lv_fragment_t * instance; + /** + * true between `create_obj_cb` and `obj_deleted_cb` + */ + bool obj_created; + /** + * true before `lv_fragment_del_obj` is called. Don't touch any object if this is true + */ + bool destroying_obj; + /** + * true if this fragment is in navigation stack that can be popped + */ + bool in_stack; +} lv_fragment_managed_states_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create fragment manager instance + * @param parent Parent fragment if this manager is placed inside another fragment, can be null. + * @return Fragment manager instance + */ +lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent); + +/** + * Destroy fragment manager instance + * @param manager Fragment manager instance + */ +void lv_fragment_manager_del(lv_fragment_manager_t * manager); + +/** + * Create object of all fragments managed by this manager. + * @param manager Fragment manager instance + */ +void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager); + +/** + * Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted. + * @param manager Fragment manager instance + */ +void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager); + +/** + * Attach fragment to manager, and add to container. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container); + +/** + * Detach and destroy fragment. If fragment is in navigation stack, remove from it. + * @param manager Fragment manager instance + * @param fragment Fragment instance + */ +void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment); + +/** + * Attach fragment to manager and add to navigation stack. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container); + +/** + * Remove the top-most fragment for stack + * @param manager Fragment manager instance + * @return true if there is fragment to pop + */ +bool lv_fragment_manager_pop(lv_fragment_manager_t * manager); + +/** + * Replace fragment. Old item in the stack will be removed. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment, + lv_obj_t * const * container); + +/** + * Send event to top-most fragment + * @param manager Fragment manager instance + * @param code User-defined ID of event + * @param userdata User-defined data + * @return true if fragment returned true + */ +bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata); + +/** + * Get stack size of this fragment manager + * @param manager Fragment manager instance + * @return Stack size of this fragment manager + */ +size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager); + +/** + * Get top most fragment instance + * @param manager Fragment manager instance + * @return Top most fragment instance + */ +lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager); + +/** + * Find first fragment instance in the container + * @param manager Fragment manager instance + * @param container Container which target fragment added to + * @return First fragment instance in the container + */ +lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container); + +/** + * Get parent fragment + * @param manager Fragment manager instance + * @return Parent fragment instance + */ +lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager); + + +/** + * Create a fragment instance. + * + * @param cls Fragment class. This fragment must return non null object. + * @param args Arguments assigned by fragment manager + * @return Fragment instance + */ +lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args); + +/** + * Destroy a fragment. + * @param fragment Fragment instance. + */ +void lv_fragment_del(lv_fragment_t * fragment); + +/** + * Get associated manager of this fragment + * @param fragment Fragment instance + * @return Fragment manager instance + */ +lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment); + +/** + * Get container object of this fragment + * @param fragment Fragment instance + * @return Reference to container object + */ +lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment); + +/** + * Get parent fragment of this fragment + * @param fragment Fragment instance + * @return Parent fragment + */ +lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment); + +/** + * Create object by fragment. + * + * @param fragment Fragment instance. + * @param container Container of the objects should be created upon. + * @return Created object + */ +lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container); + +/** + * Delete created object of a fragment + * + * @param fragment Fragment instance. + */ +void lv_fragment_del_obj(lv_fragment_t * fragment); + +/** + * Destroy obj in fragment, and recreate them. + * @param fragment Fragment instance + */ +void lv_fragment_recreate_obj(lv_fragment_t * fragment); + + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FRAGMENT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FRAGMENT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c new file mode 100644 index 000000000..e8ee84f49 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c @@ -0,0 +1,280 @@ +/** + * @file lv_fragment_manager.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_fragment.h" + +#if LV_USE_FRAGMENT + +#include "../../../misc/lv_ll.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct _lv_fragment_stack_item_t { + lv_fragment_managed_states_t * states; +} lv_fragment_stack_item_t; + +struct _lv_fragment_manager_t { + lv_fragment_t * parent; + /** + * Linked list to store attached fragments + */ + lv_ll_t attached; + /** + * Linked list to store fragments in stack + */ + lv_ll_t stack; +}; + + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void item_create_obj(lv_fragment_managed_states_t * item); + +static void item_del_obj(lv_fragment_managed_states_t * item); + +static void item_del_fragment(lv_fragment_managed_states_t * item); + +static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, + lv_obj_t * const * container); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent) +{ + lv_fragment_manager_t * instance = lv_mem_alloc(sizeof(lv_fragment_manager_t)); + lv_memset_00(instance, sizeof(lv_fragment_manager_t)); + instance->parent = parent; + _lv_ll_init(&instance->attached, sizeof(lv_fragment_managed_states_t)); + _lv_ll_init(&instance->stack, sizeof(lv_fragment_stack_item_t)); + return instance; +} + +void lv_fragment_manager_del(lv_fragment_manager_t * manager) +{ + LV_ASSERT_NULL(manager); + lv_fragment_managed_states_t * states; + _LV_LL_READ_BACK(&manager->attached, states) { + item_del_obj(states); + item_del_fragment(states); + } + _lv_ll_clear(&manager->attached); + _lv_ll_clear(&manager->stack); + lv_mem_free(manager); +} + +void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager) +{ + LV_ASSERT_NULL(manager); + lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); + lv_fragment_managed_states_t * states = NULL; + _LV_LL_READ(&manager->attached, states) { + if(states->in_stack && top->states != states) { + /*Only create obj for top item in stack*/ + continue; + } + item_create_obj(states); + } +} + +void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager) +{ + LV_ASSERT_NULL(manager); + lv_fragment_managed_states_t * states = NULL; + _LV_LL_READ_BACK(&manager->attached, states) { + item_del_obj(states); + } +} + +void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container) +{ + lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container); + if(!manager->parent || manager->parent->managed->obj_created) { + item_create_obj(states); + } +} + +void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment) +{ + LV_ASSERT_NULL(manager); + LV_ASSERT_NULL(fragment); + LV_ASSERT_NULL(fragment->managed); + LV_ASSERT(fragment->managed->manager == manager); + lv_fragment_managed_states_t * states = fragment->managed; + lv_fragment_managed_states_t * prev = NULL; + bool was_top = false; + if(states->in_stack) { + void * stack_top = _lv_ll_get_tail(&manager->stack); + lv_fragment_stack_item_t * item = NULL; + _LV_LL_READ_BACK(&manager->stack, item) { + if(item->states == states) { + was_top = stack_top == item; + void * stack_prev = _lv_ll_get_prev(&manager->stack, item); + if(!stack_prev) break; + prev = ((lv_fragment_stack_item_t *) stack_prev)->states; + break; + } + } + if(item) { + _lv_ll_remove(&manager->stack, item); + lv_mem_free(item); + } + } + item_del_obj(states); + item_del_fragment(states); + _lv_ll_remove(&manager->attached, states); + lv_mem_free(states); + if(prev && was_top) { + item_create_obj(prev); + } +} + +void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container) +{ + lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); + if(top != NULL) { + item_del_obj(top->states); + } + lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container); + states->in_stack = true; + /*Add fragment to the top of the stack*/ + lv_fragment_stack_item_t * item = _lv_ll_ins_tail(&manager->stack); + lv_memset_00(item, sizeof(lv_fragment_stack_item_t)); + item->states = states; + item_create_obj(states); +} + +bool lv_fragment_manager_pop(lv_fragment_manager_t * manager) +{ + lv_fragment_t * top = lv_fragment_manager_get_top(manager); + if(top == NULL) return false; + lv_fragment_manager_remove(manager, top); + return true; +} + +void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment, + lv_obj_t * const * container) +{ + lv_fragment_t * top = lv_fragment_manager_find_by_container(manager, *container); + if(top != NULL) { + lv_fragment_manager_remove(manager, top); + } + lv_fragment_manager_add(manager, fragment, container); +} + +bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata) +{ + LV_ASSERT_NULL(manager); + lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); + if(!top) return false; + lv_fragment_managed_states_t * states = top->states; + lv_fragment_t * instance = states->instance; + if(!instance) return false; + if(lv_fragment_manager_send_event(instance->child_manager, code, userdata)) return true; + if(!states->cls->event_cb) return false; + return states->cls->event_cb(instance, code, userdata); +} + +size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager) +{ + LV_ASSERT_NULL(manager); + return _lv_ll_get_len(&manager->stack); +} + +lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager) +{ + LV_ASSERT(manager); + lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); + if(!top)return NULL; + return top->states->instance; +} + +lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container) +{ + LV_ASSERT(manager); + lv_fragment_managed_states_t * states; + _LV_LL_READ(&manager->attached, states) { + if(*states->container == container) return states->instance; + } + return NULL; +} + +lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager) +{ + LV_ASSERT_NULL(manager); + return manager->parent; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void item_create_obj(lv_fragment_managed_states_t * item) +{ + LV_ASSERT(item->instance); + lv_fragment_create_obj(item->instance, item->container ? *item->container : NULL); +} + +static void item_del_obj(lv_fragment_managed_states_t * item) +{ + lv_fragment_del_obj(item->instance); +} + +/** + * Detach, then destroy fragment + * @param item fragment states + */ +static void item_del_fragment(lv_fragment_managed_states_t * item) +{ + lv_fragment_t * instance = item->instance; + if(instance->cls->detached_cb) { + instance->cls->detached_cb(instance); + } + instance->managed = NULL; + lv_fragment_del(instance); + item->instance = NULL; +} + + +static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, + lv_obj_t * const * container) +{ + LV_ASSERT(manager); + LV_ASSERT(fragment); + LV_ASSERT(fragment->managed == NULL); + lv_fragment_managed_states_t * states = _lv_ll_ins_tail(&manager->attached); + lv_memset_00(states, sizeof(lv_fragment_managed_states_t)); + states->cls = fragment->cls; + states->manager = manager; + states->container = container; + states->instance = fragment; + fragment->managed = states; + if(fragment->cls->attached_cb) { + fragment->cls->attached_cb(fragment); + } + return states; +} + +#endif /*LV_USE_FRAGMENT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c b/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c index 874e6a982..4eec637bd 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c @@ -81,6 +81,27 @@ void lv_gridnav_remove(lv_obj_t * obj) lv_obj_remove_event_cb(obj, gridnav_event_cb); } +void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable_t anim_en) +{ + LV_ASSERT_NULL(to_focus); + lv_gridnav_dsc_t * dsc = lv_obj_get_event_user_data(cont, gridnav_event_cb); + if(dsc == NULL) { + LV_LOG_WARN("`cont` is not a gridnav container"); + return; + } + + if(obj_is_focuable(to_focus) == false) { + LV_LOG_WARN("The object to focus is not focusable"); + return; + } + + lv_obj_clear_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + lv_obj_add_state(to_focus, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + lv_obj_scroll_to_view(to_focus, anim_en); + dsc->focused_obj = to_focus; + +} + /********************** * STATIC FUNCTIONS **********************/ @@ -98,7 +119,7 @@ static void gridnav_event_cb(lv_event_t * e) if(dsc->focused_obj == NULL) dsc->focused_obj = find_first_focusable(obj); if(dsc->focused_obj == NULL) return; - uint32_t key = lv_indev_get_key(lv_indev_get_act()); + uint32_t key = lv_event_get_key(e); lv_obj_t * guess = NULL; if(key == LV_KEY_RIGHT) { @@ -327,7 +348,7 @@ static lv_obj_t * find_last_focusable(lv_obj_t * obj) { uint32_t child_cnt = lv_obj_get_child_cnt(obj); int32_t i; - for(i = child_cnt - 1; i >= 0; i++) { + for(i = child_cnt - 1; i >= 0; i--) { lv_obj_t * child = lv_obj_get_child(obj, i); if(obj_is_focuable(child)) return child; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h b/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h index ea81595de..f480ded46 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h @@ -103,6 +103,14 @@ void lv_gridnav_add(lv_obj_t * obj, lv_gridnav_ctrl_t ctrl); */ void lv_gridnav_remove(lv_obj_t * obj); +/** + * Manually focus an object on gridnav container + * @param cont pointer to a gridnav container + * @param to_focus pointer to an object to focus + * @param anim_en LV_ANIM_ON/OFF + */ +void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable_t anim_en); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c b/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c new file mode 100644 index 000000000..b1661e4f7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c @@ -0,0 +1,1198 @@ +/** + * @file lv_ime_pinyin.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_ime_pinyin.h" +#if LV_USE_IME_PINYIN != 0 + +#include + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_ime_pinyin_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_ime_pinyin_style_change_event(lv_event_t * e); +static void lv_ime_pinyin_kb_event(lv_event_t * e); +static void lv_ime_pinyin_cand_panel_event(lv_event_t * e); + +static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); +static void pinyin_input_proc(lv_obj_t * obj); +static void pinyin_page_proc(lv_obj_t * obj, uint16_t btn); +static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num); +static void pinyin_ime_clear_data(lv_obj_t * obj); + +#if LV_IME_PINYIN_USE_K9_MODE + static void pinyin_k9_init_data(lv_obj_t * obj); + static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]); + static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str); + static void pinyin_k9_fill_cand(lv_obj_t * obj); + static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir); +#endif + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_ime_pinyin_class = { + .constructor_cb = lv_ime_pinyin_constructor, + .destructor_cb = lv_ime_pinyin_destructor, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .instance_size = sizeof(lv_ime_pinyin_t), + .base_class = &lv_obj_class +}; + +#if LV_IME_PINYIN_USE_K9_MODE +static char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 20] = {\ + ",\0", "1#\0", "abc \0", "def\0", LV_SYMBOL_BACKSPACE"\0", "\n\0", + ".\0", "ghi\0", "jkl\0", "mno\0", LV_SYMBOL_KEYBOARD"\0", "\n\0", + "?\0", "pqrs\0", "tuv\0", "wxyz\0", LV_SYMBOL_NEW_LINE"\0", "\n\0", + LV_SYMBOL_LEFT"\0", "\0" + }; + +static lv_btnmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = { 1 }; +static char lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 2][LV_IME_PINYIN_K9_MAX_INPUT] = {0}; +#endif + +static char lv_pinyin_cand_str[LV_IME_PINYIN_CAND_TEXT_NUM][4]; +static char * lv_btnm_def_pinyin_sel_map[LV_IME_PINYIN_CAND_TEXT_NUM + 3]; + +#if LV_IME_PINYIN_USE_DEFAULT_DICT +lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = { + { "a", "啊" }, + { "ai", "愛" }, + { "an", "安暗案" }, + { "ba", "吧把爸八" }, + { "bai", "百白敗" }, + { "ban", "半般辦" }, + { "bang", "旁" }, + { "bao", "保薄包報" }, + { "bei", "被背悲北杯備" }, + { "ben", "本" }, + { "bi", "必比避鼻彼筆秘閉" }, + { "bian", "便邊變変辺" }, + { "biao", "表標" }, + { "bie", "別" }, + { "bing", "病並氷" }, + { "bo", "波薄泊" }, + { "bu", "不布步部捕補歩" }, + { "ca", "察" }, + { "cai", "才材菜財採" }, + { "can", "参残參" }, + { "ce", "策側" }, + { "ceng", "曾" }, + { "cha", "差查茶" }, + { "chai", "差" }, + { "chan", "產産單" }, + { "chang", "場廠" }, + { "chao", "超朝" }, + { "che", "車" }, + { "cheng", "成程乗" }, + { "chi", "尺吃持赤池遅歯" }, + { "chong", "充种重種" }, + { "chu", "出初楚触處処" }, + { "chuan", "川船傳" }, + { "chuang", "創窓" }, + { "chun", "春" }, + { "ci", "此次辞差" }, + { "cong", "從従" }, + { "cu", "卒" }, + { "cun", "存村" }, + { "cuo", "錯" }, + { "da", "大打答達" }, + { "dai", "代待帯帶貸" }, + { "dan", "但担擔誕單単" }, + { "dang", "当党當黨" }, + { "dao", "到道盗導島辺" }, + { "de", "的得" }, + { "dei", "" }, + { "deng", "等" }, + { "di", "地得低底弟第締" }, + { "dian", "点电店點電" }, + { "diao", "調" }, + { "ding", "定町" }, + { "dong", "冬東動働凍" }, + { "du", "独度都渡読" }, + { "duan", "段断短斷" }, + { "dui", "對対" }, + { "duo", "多駄" }, + { "e", "嗯悪" }, + { "en", "嗯" }, + { "er", "而耳二兒" }, + { "fa", "乏法發発髪" }, + { "fan", "反返犯番仮販飯範払" }, + { "fang", "方放房坊訪" }, + { "fei", "非飛費" }, + { "fen", "分份" }, + { "feng", "風豐" }, + { "fou", "否不" }, + { "fu", "父夫富服符付附府幅婦復複負払" }, + { "gai", "改概該" }, + { "gan", "甘感敢" }, + { "gang", "港剛" }, + { "gao", "告高" }, + { "ge", "各格歌革割個" }, + { "gei", "給" }, + { "gen", "跟根" }, + { "geng", "更" }, + { "gong", "工共供功公" }, + { "gou", "夠構溝" }, + { "gu", "古故鼓" }, + { "guai", "掛" }, + { "guan", "官管慣館觀関關" }, + { "guang", "光広" }, + { "gui", "規帰" }, + { "guo", "果国裏菓國過" }, + { "hai", "孩海害還" }, + { "han", "寒漢" }, + { "hang", "航行" }, + { "hao", "好号" }, + { "he", "合和喝何荷" }, + { "hei", "黒" }, + { "hen", "很" }, + { "heng", "行横" }, + { "hou", "厚喉候後" }, + { "hu", "乎呼湖護" }, + { "hua", "化画花話畫劃" }, + { "huai", "壊劃" }, + { "huan", "緩環歡還換" }, + { "huang", "黄" }, + { "hui", "回会慧絵揮會" }, + { "hun", "混婚" }, + { "huo", "活或火獲" }, + { "i", "" }, + { "ji", "己计及机既急季寄技即集基祭系奇紀積計記済幾際極繼績機濟" }, + { "jia", "家加價" }, + { "jian", "件建健肩見減間検簡漸" }, + { "jiang", "降強講將港" }, + { "jiao", "叫教交角覚覺較學" }, + { "jie", "介借接姐皆届界解結階節價" }, + { "jin", "今近禁金僅進" }, + { "jing", "京境景静精經経" }, + { "jiu", "就久九酒究" }, + { "ju", "句具局居決挙據舉" }, + { "jue", "角覚覺" }, + { "jun", "均" }, + { "kai", "開" }, + { "kan", "看刊" }, + { "kang", "康" }, + { "kao", "考" }, + { "ke", "可刻科克客渇課" }, + { "ken", "肯" }, + { "kong", "空控" }, + { "kou", "口" }, + { "ku", "苦庫" }, + { "kuai", "快塊会會" }, + { "kuang", "況" }, + { "kun", "困" }, + { "kuo", "括拡適" }, + { "la", "拉啦落" }, + { "lai", "来來頼" }, + { "lao", "老絡落" }, + { "le", "了楽樂" }, + { "lei", "類" }, + { "leng", "冷" }, + { "li", "力立利理例礼離麗裡勵歷" }, + { "lian", "連練臉聯" }, + { "liang", "良量涼兩両" }, + { "liao", "料" }, + { "lie", "列" }, + { "lin", "林隣賃" }, + { "ling", "另令領" }, + { "liu", "六留流" }, + { "lu", "律路録緑陸履慮" }, + { "lv", "旅" }, + { "lun", "輪論" }, + { "luo", "落絡" }, + { "ma", "媽嗎嘛" }, + { "mai", "買売" }, + { "man", "滿" }, + { "mang", "忙" }, + { "mao", "毛猫貿" }, + { "me", "麼" }, + { "mei", "美妹每沒毎媒" }, + { "men", "們" }, + { "mi", "米密秘" }, + { "mian", "免面勉眠" }, + { "miao", "描" }, + { "min", "民皿" }, + { "ming", "命明名" }, + { "mo", "末模麼" }, + { "mou", "某" }, + { "mu", "母木目模" }, + { "na", "那哪拿內南" }, + { "nan", "男南難" }, + { "nao", "腦" }, + { "ne", "那哪呢" }, + { "nei", "内那哪內" }, + { "neng", "能" }, + { "ni", "你妳呢" }, + { "nian", "年念" }, + { "niang", "娘" }, + { "nin", "您" }, + { "ning", "凝" }, + { "niu", "牛" }, + { "nong", "農濃" }, + { "nu", "女努" }, + { "nuan", "暖" }, + { "o", "" }, + { "ou", "歐" }, + { "pa", "怕" }, + { "pian", "片便" }, + { "pai", "迫派排" }, + { "pan", "判番" }, + { "pang", "旁" }, + { "pei", "配" }, + { "peng", "朋" }, + { "pi", "疲否" }, + { "pin", "品貧" }, + { "ping", "平評" }, + { "po", "迫破泊頗" }, + { "pu", "普僕" }, + { "qi", "起其奇七气期泣企妻契気" }, + { "qian", "嵌浅千前鉛錢針" }, + { "qiang", "強將" }, + { "qiao", "橋繰" }, + { "qie", "且切契" }, + { "qin", "寝勤親" }, + { "qing", "青清情晴輕頃請軽" }, + { "qiu", "求秋球" }, + { "qu", "去取趣曲區" }, + { "quan", "全犬券" }, + { "que", "缺確卻" }, + { "ran", "然" }, + { "rang", "讓" }, + { "re", "熱" }, + { "ren", "人任認" }, + { "reng", "仍" }, + { "ri", "日" }, + { "rong", "容" }, + { "rou", "弱若肉" }, + { "ru", "如入" }, + { "ruan", "軟" }, + { "sai", "賽" }, + { "san", "三" }, + { "sao", "騒繰" }, + { "se", "色" }, + { "sen", "森" }, + { "sha", "砂" }, + { "shan", "善山單" }, + { "shang", "上尚商" }, + { "shao", "少紹" }, + { "shaung", "雙" }, + { "she", "社射設捨渉" }, + { "shei", "誰" }, + { "shen", "什申深甚身伸沈神" }, + { "sheng", "生声昇勝乗聲" }, + { "shi", "是失示食时事式十石施使世实史室市始柿氏士仕拭時視師試適実實識" }, + { "shou", "手首守受授" }, + { "shu", "束数暑殊樹書屬輸術" }, + { "shui", "水説說誰" }, + { "shuo", "数説說" }, + { "si", "思寺司四私似死価" }, + { "song", "送" }, + { "su", "速宿素蘇訴" }, + { "suan", "算酸" }, + { "sui", "隨雖歲歳" }, + { "sun", "孫" }, + { "suo", "所" }, + { "ta", "她他它牠" }, + { "tai", "太台態臺" }, + { "tan", "探談曇" }, + { "tang", "糖" }, + { "tao", "桃逃套討" }, + { "te", "特" }, + { "ti", "体提替題體戻" }, + { "tian", "天田" }, + { "tiao", "条條調" }, + { "tie", "鉄" }, + { "ting", "停庭聽町" }, + { "tong", "同童通痛统統" }, + { "tou", "投透頭" }, + { "tu", "土徒茶図" }, + { "tuan", "團" }, + { "tui", "推退" }, + { "tuo", "脱駄" }, + { "u", "" }, + { "v", "" }, + { "wai", "外" }, + { "wan", "完万玩晩腕灣" }, + { "wang", "忘望亡往網" }, + { "wei", "危位未味委為謂維違圍" }, + { "wen", "文温問聞" }, + { "wo", "我" }, + { "wu", "午物五無屋亡鳥務汚" }, + { "xi", "夕息西洗喜系昔席希析嬉膝細習係" }, + { "xia", "下夏狭暇" }, + { "xian", "先限嫌洗現見線顯" }, + { "xiang", "向相香像想象降項詳響" }, + { "xiao", "小笑消效校削咲" }, + { "xie", "写携些解邪械協謝寫契" }, + { "xin", "心信新辛" }, + { "xing", "行形性幸型星興" }, + { "xiong", "兄胸" }, + { "xiu", "休秀修" }, + { "xu", "須需許續緒続" }, + { "xuan", "選懸" }, + { "xue", "学雪削靴學" }, + { "xun", "訓訊" }, + { "ya", "呀押壓" }, + { "yan", "言顔研煙嚴厳験驗塩" }, + { "yang", "央洋陽樣様" }, + { "yao", "要揺腰薬曜" }, + { "ye", "也野夜邪業葉" }, + { "yi", "一已亦依以移意医易伊役異億義議藝醫訳" }, + { "yin", "因引音飲銀" }, + { "ying", "英迎影映應營営" }, + { "yong", "永用泳擁" }, + { "you", "又有右友由尤油遊郵誘優" }, + { "yu", "予育余雨浴欲愈御宇域語於魚與込" }, + { "yuan", "元原源院員円園遠猿願" }, + { "yue", "月越約楽" }, + { "yun", "雲伝運" }, + { "za", "雑" }, + { "zai", "在再載災" }, + { "zang", "蔵" }, + { "zao", "早造" }, + { "ze", "則擇責" }, + { "zen", "怎" }, + { "zeng", "曾增増" }, + { "zha", "札" }, + { "zhai", "宅擇" }, + { "zhan", "站展戰戦" }, + { "zhang", "丈長障帳張" }, + { "zhao", "找着朝招" }, + { "zhe", "者這" }, + { "zhen", "真震針" }, + { "zheng", "正整争政爭" }, + { "zhi", "之只知支止制至治直指值置智値紙製質誌織隻識職執" }, + { "zhong", "中种終重種眾" }, + { "zhou", "周州昼宙洲週" }, + { "zhu", "助主住柱株祝逐注著諸屬術" }, + { "zhuan", "专專転" }, + { "zhuang", "状狀" }, + { "zhui", "追" }, + { "zhun", "準" }, + { "zhuo", "着" }, + { "zi", "子自字姉資" }, + { "zong", "總" }, + { "zuo", "左做昨坐座作" }, + { "zu", "足祖族卒組" }, + { "zui", "最酔" }, + { "zou", "走" }, + {NULL, NULL} +}; +#endif + + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the keyboard of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @param dict pointer to a Pinyin input method keyboard + */ +void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb) +{ + if(kb) { + LV_ASSERT_OBJ(kb, &lv_keyboard_class); + } + + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + pinyin_ime->kb = kb; + lv_obj_add_event_cb(pinyin_ime->kb, lv_ime_pinyin_kb_event, LV_EVENT_VALUE_CHANGED, obj); + lv_obj_align_to(pinyin_ime->cand_panel, pinyin_ime->kb, LV_ALIGN_OUT_TOP_MID, 0, 0); +} + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @param dict pointer to a Pinyin input method dictionary + */ +void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + init_pinyin_dict(obj, dict); +} + +/** + * Set mode, 26-key input(k26) or 9-key input(k9). + * @param obj pointer to a Pinyin input method object + * @param mode the mode from 'lv_keyboard_mode_t' + */ +void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + LV_ASSERT_OBJ(pinyin_ime->kb, &lv_keyboard_class); + + pinyin_ime->mode = mode; + +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_k9_init_data(obj); + lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1, (const char *)lv_btnm_def_pinyin_k9_map, + (const)default_kb_ctrl_k9_map); + lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1); + } +#endif +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin IME object + * @return pointer to the Pinyin IME keyboard + */ +lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + return pinyin_ime->kb; +} + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @return pointer to the Pinyin input method candidate panel + */ +lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + return pinyin_ime->cand_panel; +} + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @return pointer to the Pinyin input method dictionary + */ +lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + return pinyin_ime->dict; +} + +/*===================== + * Other functions + *====================*/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + uint16_t py_str_i = 0; + uint16_t btnm_i = 0; + for(btnm_i = 0; btnm_i < (LV_IME_PINYIN_CAND_TEXT_NUM + 3); btnm_i++) { + if(btnm_i == 0) { + lv_btnm_def_pinyin_sel_map[btnm_i] = "<"; + } + else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) { + lv_btnm_def_pinyin_sel_map[btnm_i] = ">"; + } + else if(btnm_i == (LV_IME_PINYIN_CAND_TEXT_NUM + 2)) { + lv_btnm_def_pinyin_sel_map[btnm_i] = ""; + } + else { + lv_pinyin_cand_str[py_str_i][0] = ' '; + lv_btnm_def_pinyin_sel_map[btnm_i] = lv_pinyin_cand_str[py_str_i]; + py_str_i++; + } + } + + pinyin_ime->mode = LV_IME_PINYIN_MODE_K26; + pinyin_ime->py_page = 0; + pinyin_ime->ta_count = 0; + pinyin_ime->cand_num = 0; + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + lv_memset_00(pinyin_ime->py_num, sizeof(pinyin_ime->py_num)); + lv_memset_00(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos)); + + lv_obj_set_size(obj, LV_PCT(100), LV_PCT(55)); + lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0); + +#if LV_IME_PINYIN_USE_DEFAULT_DICT + init_pinyin_dict(obj, lv_ime_pinyin_def_dict); +#endif + + /* Init pinyin_ime->cand_panel */ + pinyin_ime->cand_panel = lv_btnmatrix_create(lv_scr_act()); + lv_btnmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map); + lv_obj_set_size(pinyin_ime->cand_panel, LV_PCT(100), LV_PCT(5)); + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + + lv_btnmatrix_set_one_checked(pinyin_ime->cand_panel, true); + + /* Set cand_panel style*/ + // Default style + lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, 0); + lv_obj_set_style_border_width(pinyin_ime->cand_panel, 0, 0); + lv_obj_set_style_pad_all(pinyin_ime->cand_panel, 8, 0); + lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0); + lv_obj_set_style_radius(pinyin_ime->cand_panel, 0, 0); + lv_obj_set_style_pad_gap(pinyin_ime->cand_panel, 0, 0); + lv_obj_set_style_base_dir(pinyin_ime->cand_panel, LV_BASE_DIR_LTR, 0); + + // LV_PART_ITEMS style + lv_obj_set_style_radius(pinyin_ime->cand_panel, 12, LV_PART_ITEMS); + lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS); + lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS); + lv_obj_set_style_shadow_opa(pinyin_ime->cand_panel, LV_OPA_0, LV_PART_ITEMS); + + // LV_PART_ITEMS | LV_STATE_PRESSED style + lv_obj_set_style_bg_opa(pinyin_ime->cand_panel, LV_OPA_COVER, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_set_style_bg_color(pinyin_ime->cand_panel, lv_color_white(), LV_PART_ITEMS | LV_STATE_PRESSED); + + /* event handler */ + lv_obj_add_event_cb(pinyin_ime->cand_panel, lv_ime_pinyin_cand_panel_event, LV_EVENT_VALUE_CHANGED, obj); + lv_obj_add_event_cb(obj, lv_ime_pinyin_style_change_event, LV_EVENT_STYLE_CHANGED, NULL); + +#if LV_IME_PINYIN_USE_K9_MODE + pinyin_ime->k9_input_str_len = 0; + pinyin_ime->k9_py_ll_pos = 0; + pinyin_ime->k9_legal_py_count = 0; + lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + + pinyin_k9_init_data(obj); + + _lv_ll_init(&(pinyin_ime->k9_legal_py_ll), sizeof(ime_pinyin_k9_py_str_t)); +#endif +} + + +static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + if(lv_obj_is_valid(pinyin_ime->kb)) + lv_obj_del(pinyin_ime->kb); + + if(lv_obj_is_valid(pinyin_ime->cand_panel)) + lv_obj_del(pinyin_ime->cand_panel); +} + + +static void lv_ime_pinyin_kb_event(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * kb = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_user_data(e); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + +#if LV_IME_PINYIN_USE_K9_MODE + static const char * k9_py_map[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; +#endif + + if(code == LV_EVENT_VALUE_CHANGED) { + uint16_t btn_id = lv_btnmatrix_get_selected_btn(kb); + if(btn_id == LV_BTNMATRIX_BTN_NONE) return; + + const char * txt = lv_btnmatrix_get_btn_text(kb, lv_btnmatrix_get_selected_btn(kb)); + if(txt == NULL) return; + +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + uint16_t tmp_btn_str_len = strlen(pinyin_ime->input_char); + if((btn_id >= 16) && (tmp_btn_str_len > 0) && (btn_id < (16 + LV_IME_PINYIN_K9_CAND_TEXT_NUM))) { + tmp_btn_str_len = strlen(pinyin_ime->input_char); + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + strcat(pinyin_ime->input_char, txt); + pinyin_input_proc(obj); + + for(int index = 0; index < (pinyin_ime->ta_count + tmp_btn_str_len); index++) { + lv_textarea_del_char(ta); + } + + pinyin_ime->ta_count = tmp_btn_str_len; + pinyin_ime->k9_input_str_len = tmp_btn_str_len; + lv_textarea_add_text(ta, pinyin_ime->input_char); + + return; + } + } +#endif + + if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { + pinyin_ime_clear_data(obj); + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + } + else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { + // del input char + if(pinyin_ime->ta_count > 0) { + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) + pinyin_ime->input_char[pinyin_ime->ta_count - 1] = '\0'; +#if LV_IME_PINYIN_USE_K9_MODE + else + pinyin_ime->k9_input_str[pinyin_ime->ta_count - 1] = '\0'; +#endif + + pinyin_ime->ta_count = pinyin_ime->ta_count - 1; + if(pinyin_ime->ta_count <= 0) { + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); +#if LV_IME_PINYIN_USE_K9_MODE + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); +#endif + } + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { + pinyin_input_proc(obj); + } +#if LV_IME_PINYIN_USE_K9_MODE + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char) - 1; + pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map); + pinyin_k9_fill_cand(obj); + pinyin_input_proc(obj); + } +#endif + } + } + else if((strcmp(txt, "ABC") == 0) || (strcmp(txt, "abc") == 0) || (strcmp(txt, "1#") == 0)) { + pinyin_ime->ta_count = 0; + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + return; + } + else if(strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { + lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K9); + } + else { + lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K26); + lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER); + } + pinyin_ime_clear_data(obj); + } + else if(strcmp(txt, LV_SYMBOL_OK) == 0) { + pinyin_ime_clear_data(obj); + } + else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) && ((txt[0] >= 'a' && txt[0] <= 'z') || (txt[0] >= 'A' && + txt[0] <= 'Z'))) { + strcat(pinyin_ime->input_char, txt); + pinyin_input_proc(obj); + pinyin_ime->ta_count++; + } +#if LV_IME_PINYIN_USE_K9_MODE + else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) && (txt[0] >= 'a' && txt[0] <= 'z')) { + for(uint16_t i = 0; i < 8; i++) { + if((strcmp(txt, k9_py_map[i]) == 0) || (strcmp(txt, "abc ") == 0)) { + if(strcmp(txt, "abc ") == 0) pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]) + 1; + else pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]); + pinyin_ime->k9_input_str[pinyin_ime->ta_count] = 50 + i; + + break; + } + } + pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map); + pinyin_k9_fill_cand(obj); + pinyin_input_proc(obj); + } + else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { + pinyin_k9_cand_page_proc(obj, 0); + } + else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { + pinyin_k9_cand_page_proc(obj, 1); + } +#endif + } +} + + +static void lv_ime_pinyin_cand_panel_event(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * cand_panel = lv_event_get_target(e); + lv_obj_t * obj = (lv_obj_t *)lv_event_get_user_data(e); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + if(code == LV_EVENT_VALUE_CHANGED) { + uint32_t id = lv_btnmatrix_get_selected_btn(cand_panel); + if(id == 0) { + pinyin_page_proc(obj, 0); + return; + } + if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) { + pinyin_page_proc(obj, 1); + return; + } + + const char * txt = lv_btnmatrix_get_btn_text(cand_panel, id); + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + uint16_t index = 0; + for(index = 0; index < pinyin_ime->ta_count; index++) + lv_textarea_del_char(ta); + + lv_textarea_add_text(ta, txt); + + pinyin_ime_clear_data(obj); + } +} + + +static void pinyin_input_proc(lv_obj_t * obj) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + pinyin_ime->cand_str = pinyin_search_matching(obj, pinyin_ime->input_char, &pinyin_ime->cand_num); + if(pinyin_ime->cand_str == NULL) { + return; + } + + pinyin_ime->py_page = 0; + + for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { + memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); + lv_pinyin_cand_str[i][0] = ' '; + } + + // fill buf + for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) { + for(uint8_t j = 0; j < 3; j++) { + lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[i * 3 + j]; + } + } + + lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); +} + +static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + uint16_t page_num = pinyin_ime->cand_num / LV_IME_PINYIN_CAND_TEXT_NUM; + uint16_t sur = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM; + + if(dir == 0) { + if(pinyin_ime->py_page) { + pinyin_ime->py_page--; + } + } + else { + if(sur == 0) { + page_num -= 1; + } + if(pinyin_ime->py_page < page_num) { + pinyin_ime->py_page++; + } + else return; + } + + for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { + memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); + lv_pinyin_cand_str[i][0] = ' '; + } + + // fill buf + uint16_t offset = pinyin_ime->py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM); + for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) { + if((sur > 0) && (pinyin_ime->py_page == page_num)) { + if(i > sur) + break; + } + for(uint8_t j = 0; j < 3; j++) { + lv_pinyin_cand_str[i][j] = pinyin_ime->cand_str[offset + (i * 3) + j]; + } + } +} + + +static void lv_ime_pinyin_style_change_event(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_target(e); + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + if(code == LV_EVENT_STYLE_CHANGED) { + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + lv_obj_set_style_text_font(pinyin_ime->cand_panel, font, 0); + } +} + + +static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + char headletter = 'a'; + uint16_t offset_sum = 0; + uint16_t offset_count = 0; + uint16_t letter_calc = 0; + + pinyin_ime->dict = dict; + + for(uint16_t i = 0; ; i++) { + if((NULL == (dict[i].py)) || (NULL == (dict[i].py_mb))) { + headletter = dict[i - 1].py[0]; + letter_calc = headletter - 'a'; + pinyin_ime->py_num[letter_calc] = offset_count; + break; + } + + if(headletter == (dict[i].py[0])) { + offset_count++; + } + else { + headletter = dict[i].py[0]; + letter_calc = headletter - 'a'; + pinyin_ime->py_num[letter_calc - 1] = offset_count; + offset_sum += offset_count; + pinyin_ime->py_pos[letter_calc] = offset_sum; + + offset_count = 1; + } + } +} + + +static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + lv_pinyin_dict_t * cpHZ; + uint8_t index, len = 0, offset; + volatile uint8_t count = 0; + + if(*py_str == '\0') return NULL; + if(*py_str == 'i') return NULL; + if(*py_str == 'u') return NULL; + if(*py_str == 'v') return NULL; + + offset = py_str[0] - 'a'; + len = strlen(py_str); + + cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; + count = pinyin_ime->py_num[offset]; + + while(count--) { + for(index = 0; index < len; index++) { + if(*(py_str + index) != *((cpHZ->py) + index)) { + break; + } + } + + // perfect match + if(len == 1 || index == len) { + // The Chinese character in UTF-8 encoding format is 3 bytes + * cand_num = strlen((const char *)(cpHZ->py_mb)) / 3; + return (char *)(cpHZ->py_mb); + } + cpHZ++; + } + return NULL; +} + +static void pinyin_ime_clear_data(lv_obj_t * obj) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + +#if LV_IME_PINYIN_USE_K9_MODE + if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + pinyin_ime->k9_input_str_len = 0; + pinyin_ime->k9_py_ll_pos = 0; + pinyin_ime->k9_legal_py_count = 0; + lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + } +#endif + + pinyin_ime->ta_count = 0; + lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str))); + lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); +} + + +#if LV_IME_PINYIN_USE_K9_MODE +static void pinyin_k9_init_data(lv_obj_t * obj) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + uint16_t py_str_i = 0; + uint16_t btnm_i = 0; + for(btnm_i = 19; btnm_i < (LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21); btnm_i++) { + if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM) { + strcpy(lv_pinyin_k9_cand_str[py_str_i], LV_SYMBOL_RIGHT"\0"); + } + else if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1) { + strcpy(lv_pinyin_k9_cand_str[py_str_i], "\0"); + } + else { + strcpy(lv_pinyin_k9_cand_str[py_str_i], " \0"); + } + + lv_btnm_def_pinyin_k9_map[btnm_i] = lv_pinyin_k9_cand_str[py_str_i]; + py_str_i++; + } + + default_kb_ctrl_k9_map[0] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[4] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[5] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[9] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[10] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[14] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[15] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; +} + +static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + uint16_t len = strlen(k9_input); + + if((len == 0) || (len >= LV_IME_PINYIN_K9_MAX_INPUT)) { + return; + } + + char py_comp[LV_IME_PINYIN_K9_MAX_INPUT] = {0}; + int mark[LV_IME_PINYIN_K9_MAX_INPUT] = {0}; + int index = 0; + int flag = 0; + int count = 0; + + uint32_t ll_len = 0; + ime_pinyin_k9_py_str_t * ll_index = NULL; + + ll_len = _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll); + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + + while(index != -1) { + if(index == len) { + if(pinyin_k9_is_valid_py(obj, py_comp)) { + if((count >= ll_len) || (ll_len == 0)) { + ll_index = _lv_ll_ins_tail(&pinyin_ime->k9_legal_py_ll); + strcpy(ll_index->py_str, py_comp); + } + else if((count < ll_len)) { + strcpy(ll_index->py_str, py_comp); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); + } + count++; + } + index--; + } + else { + flag = mark[index]; + if(flag < strlen(py9_map[k9_input[index] - '2'])) { + py_comp[index] = py9_map[k9_input[index] - '2'][flag]; + mark[index] = mark[index] + 1; + index++; + } + else { + mark[index] = 0; + index--; + } + } + } + + if(count > 0) { + pinyin_ime->ta_count++; + pinyin_ime->k9_legal_py_count = count; + } +} + + +/*true: visible; false: not visible*/ +static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + lv_pinyin_dict_t * cpHZ = NULL; + uint8_t index = 0, len = 0, offset = 0; + uint16_t ret = 1; + volatile uint8_t count = 0; + + if(*py_str == '\0') return false; + if(*py_str == 'i') return false; + if(*py_str == 'u') return false; + if(*py_str == 'v') return false; + + offset = py_str[0] - 'a'; + len = strlen(py_str); + + cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; + count = pinyin_ime->py_num[offset]; + + while(count--) { + for(index = 0; index < len; index++) { + if(*(py_str + index) != *((cpHZ->py) + index)) { + break; + } + } + + // perfect match + if(len == 1 || index == len) { + return true; + } + cpHZ++; + } + return false; +} + + +static void pinyin_k9_fill_cand(lv_obj_t * obj) +{ + static uint16_t len = 0; + uint16_t index = 0, tmp_len = 0; + ime_pinyin_k9_py_str_t * ll_index = NULL; + + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + tmp_len = pinyin_ime->k9_legal_py_count; + + if(tmp_len != len) { + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + len = tmp_len; + } + + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + strcpy(pinyin_ime->input_char, ll_index->py_str); + while(ll_index) { + if((index >= LV_IME_PINYIN_K9_CAND_TEXT_NUM) || \ + (index >= pinyin_ime->k9_legal_py_count)) + break; + + strcpy(lv_pinyin_k9_cand_str[index], ll_index->py_str); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + index++; + } + pinyin_ime->k9_py_ll_pos = index; + + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + for(index = 0; index < pinyin_ime->k9_input_str_len; index++) { + lv_textarea_del_char(ta); + } + pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char); + lv_textarea_add_text(ta, pinyin_ime->input_char); +} + + +static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) +{ + lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + uint16_t ll_len = _lv_ll_get_len(&pinyin_ime->k9_legal_py_ll); + + if((ll_len > LV_IME_PINYIN_K9_CAND_TEXT_NUM) && (pinyin_ime->k9_legal_py_count > LV_IME_PINYIN_K9_CAND_TEXT_NUM)) { + ime_pinyin_k9_py_str_t * ll_index = NULL; + uint16_t tmp_btn_str_len = 0; + int count = 0; + + ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); + while(ll_index) { + if(count >= pinyin_ime->k9_py_ll_pos) break; + + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + count++; + } + + if((NULL == ll_index) && (dir == 1)) return; + + lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + + // next page + if(dir == 1) { + count = 0; + while(ll_index) { + if(count >= (LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1)) + break; + + strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ + count++; + } + pinyin_ime->k9_py_ll_pos += count - 1; + + } + // previous page + else { + count = LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1; + ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); + while(ll_index) { + if(count < 0) break; + + strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the previous list*/ + count--; + } + + if(pinyin_ime->k9_py_ll_pos > LV_IME_PINYIN_K9_CAND_TEXT_NUM) + pinyin_ime->k9_py_ll_pos -= 1; + } + + lv_textarea_set_cursor_pos(ta, LV_TEXTAREA_CURSOR_LAST); + } +} + +#endif /*LV_IME_PINYIN_USE_K9_MODE*/ + +#endif /*LV_USE_IME_PINYIN*/ + diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h b/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h new file mode 100644 index 000000000..3ff7bb980 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h @@ -0,0 +1,145 @@ +/** + * @file lv_ime_pinyin.h + * + */ +#ifndef LV_IME_PINYIN_H +#define LV_IME_PINYIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_IME_PINYIN != 0 + +/********************* + * DEFINES + *********************/ +#define LV_IME_PINYIN_K9_MAX_INPUT 7 + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_IME_PINYIN_MODE_K26, + LV_IME_PINYIN_MODE_K9, +} lv_ime_pinyin_mode_t; + +/*Data of pinyin_dict*/ +typedef struct { + const char * const py; + const char * const py_mb; +} lv_pinyin_dict_t; + +/*Data of 9-key input(k9) mode*/ +typedef struct { + char py_str[7]; +} ime_pinyin_k9_py_str_t; + +/*Data of lv_ime_pinyin*/ +typedef struct { + lv_obj_t obj; + lv_obj_t * kb; + lv_obj_t * cand_panel; + lv_pinyin_dict_t * dict; + lv_ll_t k9_legal_py_ll; + char * cand_str; /* Candidate string */ + char input_char[16]; /* Input box character */ +#if LV_IME_PINYIN_USE_K9_MODE + char k9_input_str[LV_IME_PINYIN_K9_MAX_INPUT]; /* 9-key input(k9) mode input string */ + uint16_t k9_py_ll_pos; /* Current pinyin map pages(k9) */ + uint16_t k9_legal_py_count; /* Count of legal Pinyin numbers(k9) */ + uint16_t k9_input_str_len; /* 9-key input(k9) mode input string max len */ +#endif + uint16_t ta_count; /* The number of characters entered in the text box this time */ + uint16_t cand_num; /* Number of candidates */ + uint16_t py_page; /* Current pinyin map pages(k26) */ + uint16_t py_num[26]; /* Number and length of Pinyin */ + uint16_t py_pos[26]; /* Pinyin position */ + uint8_t mode : 1; /* Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1. */ +} lv_ime_pinyin_t; + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the keyboard of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @param dict pointer to a Pinyin input method keyboard + */ +void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb); + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @param dict pointer to a Pinyin input method dictionary + */ +void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); + +/** + * Set mode, 26-key input(k26) or 9-key input(k9). + * @param obj pointer to a Pinyin input method object + * @param mode the mode from 'lv_ime_pinyin_mode_t' + */ +void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode); + + +/*===================== + * Getter functions + *====================*/ + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin IME object + * @return pointer to the Pinyin IME keyboard + */ +lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj); + + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @return pointer to the Pinyin input method candidate panel + */ +lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj); + + +/** + * Set the dictionary of Pinyin input method. + * @param obj pointer to a Pinyin input method object + * @return pointer to the Pinyin input method dictionary + */ +lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_IME_PINYIN*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_IME_PINYIN*/ + + diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c b/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c new file mode 100644 index 000000000..ad4ab6023 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c @@ -0,0 +1,126 @@ +/** + * @file lv_imgfont.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_imgfont.h" + +#if LV_USE_IMGFONT + +/********************* + * DEFINES + *********************/ +#define LV_IMGFONT_PATH_MAX_LEN 64 + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_font_t * font; + lv_get_imgfont_path_cb_t path_cb; + char path[LV_IMGFONT_PATH_MAX_LEN]; +} imgfont_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static const uint8_t * imgfont_get_glyph_bitmap(const lv_font_t * font, uint32_t unicode); +static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, + uint32_t unicode, uint32_t unicode_next); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb) +{ + LV_ASSERT_MSG(LV_IMGFONT_PATH_MAX_LEN > sizeof(lv_img_dsc_t), + "LV_IMGFONT_PATH_MAX_LEN must be greater than sizeof(lv_img_dsc_t)"); + + size_t size = sizeof(imgfont_dsc_t) + sizeof(lv_font_t); + imgfont_dsc_t * dsc = (imgfont_dsc_t *)lv_mem_alloc(size); + if(dsc == NULL) return NULL; + lv_memset_00(dsc, size); + + dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(imgfont_dsc_t)); + dsc->path_cb = path_cb; + + lv_font_t * font = dsc->font; + font->dsc = dsc; + font->get_glyph_dsc = imgfont_get_glyph_dsc; + font->get_glyph_bitmap = imgfont_get_glyph_bitmap; + font->subpx = LV_FONT_SUBPX_NONE; + font->line_height = height; + font->base_line = 0; + font->underline_position = 0; + font->underline_thickness = 0; + + return dsc->font; +} + +void lv_imgfont_destroy(lv_font_t * font) +{ + if(font == NULL) { + return; + } + + imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc; + lv_mem_free(dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static const uint8_t * imgfont_get_glyph_bitmap(const lv_font_t * font, uint32_t unicode) +{ + LV_UNUSED(unicode); + LV_ASSERT_NULL(font); + imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc; + return (uint8_t *)dsc->path; +} + +static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, + uint32_t unicode, uint32_t unicode_next) +{ + LV_ASSERT_NULL(font); + + imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc; + LV_ASSERT_NULL(dsc); + if(dsc->path_cb == NULL) return false; + + if(!dsc->path_cb(dsc->font, dsc->path, LV_IMGFONT_PATH_MAX_LEN, unicode, unicode_next)) { + return false; + } + + lv_img_header_t header; + if(lv_img_decoder_get_info(dsc->path, &header) != LV_RES_OK) { + return false; + } + + dsc_out->is_placeholder = 0; + dsc_out->adv_w = header.w; + dsc_out->box_w = header.w; + dsc_out->box_h = header.h; + dsc_out->bpp = LV_IMGFONT_BPP; /* is image identifier */ + dsc_out->ofs_x = 0; + dsc_out->ofs_y = 0; + + return true; +} + +#endif /*LV_USE_IMGFONT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h b/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h new file mode 100644 index 000000000..5069b62f4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h @@ -0,0 +1,60 @@ +/** + * @file lv_imgfont.h + * + */ + +#ifndef LV_IMGFONT_H +#define LV_IMGFONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_IMGFONT + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/* gets the image path name of this character */ +typedef bool (*lv_get_imgfont_path_cb_t)(const lv_font_t * font, void * img_src, + uint16_t len, uint32_t unicode, uint32_t unicode_next); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Creates a image font with info parameter specified. + * @param height font size + * @param path_cb a function to get the image path name of character. + * @return pointer to the new imgfont or NULL if create error. + */ +lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb); + +/** + * Destroy a image font that has been created. + * @param font pointer to image font handle. + */ +void lv_imgfont_destroy(lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_IMGFONT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* LV_IMGFONT_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h b/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h index a4338666a..813e338c3 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h @@ -16,6 +16,11 @@ extern "C" { #include "snapshot/lv_snapshot.h" #include "monkey/lv_monkey.h" #include "gridnav/lv_gridnav.h" +// TASMOTA specific +// #include "fragment/lv_fragment.h" +// #include "imgfont/lv_imgfont.h" +// #include "msg/lv_msg.h" +// #include "ime/lv_ime_pinyin.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c new file mode 100644 index 000000000..8fd434d06 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c @@ -0,0 +1,172 @@ +/** + * @file lv_msg.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_msg.h" +#if LV_USE_MSG + +#include "../../../misc/lv_assert.h" +#include "../../../misc/lv_ll.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint32_t msg_id; + lv_msg_subscribe_cb_t callback; + void * user_data; + void * _priv_data; /*Internal: used only store 'obj' in lv_obj_subscribe*/ +} sub_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void notify(lv_msg_t * m); +static void obj_notify_cb(void * s, lv_msg_t * m); +static void obj_delete_event_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ +static lv_ll_t subs_ll; + +/********************** + * GLOBAL VARIABLES + **********************/ +lv_event_code_t LV_EVENT_MSG_RECEIVED; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_msg_init(void) +{ + LV_EVENT_MSG_RECEIVED = lv_event_register_id(); + _lv_ll_init(&subs_ll, sizeof(sub_dsc_t)); +} + +void * lv_msg_subsribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data) +{ + sub_dsc_t * s = _lv_ll_ins_tail(&subs_ll); + LV_ASSERT_MALLOC(s); + if(s == NULL) return NULL; + + lv_memset_00(s, sizeof(*s)); + + s->msg_id = msg_id; + s->callback = cb; + s->user_data = user_data; + return s; +} + +void * lv_msg_subsribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data) +{ + sub_dsc_t * s = lv_msg_subsribe(msg_id, obj_notify_cb, user_data); + if(s == NULL) return NULL; + s->_priv_data = obj; + + /*If not added yet, add a delete event cb which automatically unsubcribes the object*/ + sub_dsc_t * s_first = lv_obj_get_event_user_data(obj, obj_delete_event_cb); + if(s_first == NULL) { + lv_obj_add_event_cb(obj, obj_delete_event_cb, LV_EVENT_DELETE, s); + } + return s; +} + +void lv_msg_unsubscribe(void * s) +{ + LV_ASSERT_NULL(s); + _lv_ll_remove(&subs_ll, s); + lv_mem_free(s); +} + +void lv_msg_send(uint32_t msg_id, const void * payload) +{ + lv_msg_t m; + lv_memset_00(&m, sizeof(m)); + m.id = msg_id; + m.payload = payload; + notify(&m); +} + +uint32_t lv_msg_get_id(lv_msg_t * m) +{ + return m->id; +} + +const void * lv_msg_get_payload(lv_msg_t * m) +{ + return m->payload; +} + +void * lv_msg_get_user_data(lv_msg_t * m) +{ + return m->user_data; +} + +lv_msg_t * lv_event_get_msg(lv_event_t * e) +{ + if(e->code == LV_EVENT_MSG_RECEIVED) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + + + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void notify(lv_msg_t * m) +{ + sub_dsc_t * s; + _LV_LL_READ(&subs_ll, s) { + if(s->msg_id == m->id && s->callback) { + m->user_data = s->user_data; + m->_priv_data = s->_priv_data; + s->callback(s, m); + } + } +} + +static void obj_notify_cb(void * s, lv_msg_t * m) +{ + LV_UNUSED(s); + lv_event_send(m->_priv_data, LV_EVENT_MSG_RECEIVED, m); +} + +static void obj_delete_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + + sub_dsc_t * s = _lv_ll_get_head(&subs_ll); + sub_dsc_t * s_next; + while(s) { + /*On unsubscribe the list changes s becomes invalid so get next item while it's surely valid*/ + s_next = _lv_ll_get_next(&subs_ll, s); + if(s->_priv_data == obj) { + lv_msg_unsubscribe(s); + } + s = s_next; + } +} + +#endif /*LV_USE_MSG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h new file mode 100644 index 000000000..11a55b5a7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h @@ -0,0 +1,124 @@ +/** + * @file lv_msg.h + * + */ + +#ifndef LV_MSG_H +#define LV_MSG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#if LV_USE_MSG + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint32_t id; /*Identifier of the message*/ + void * user_data; /*Set the the user_data set in `lv_msg_subscribe`*/ + void * _priv_data; /*Used internally*/ + const void * payload; /*Pointer to the data of the message*/ +} lv_msg_t; + +typedef void (*lv_msg_subscribe_cb_t)(void * s, lv_msg_t * msg); + +typedef void (*lv_msg_request_cb_t)(void * r, uint32_t msg_id); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Called internally to initialize the message module + */ +void lv_msg_init(void); + +/** + * Subscribe to an `msg_id` + * @param msg_id the message ID to listen to + * @param cb callback to call if a message with `msg_id` was sent + * @param user_data arbitrary data which will be available in `cb` too + * @return pointer to a "subscribe object". It can be used the unsubscribe. + */ +void * lv_msg_subsribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data); + +/** + * Subscribe an `lv_obj` to a message. + * `LV_EVENT_MSG_RECEIVED` will be triggered if a message with matching ID was sent + * @param msg_id the message ID to listen to + * @param obj pointer to an `lv_obj` + * @param user_data arbitrary data which will be available in `cb` too + * @return pointer to a "subscribe object". It can be used the unsubscribe. + */ +void * lv_msg_subsribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data); + +/** + * Cancel a previous subscription + * @param s pointer to a "subscibe object". + * Return value of `lv_msg_subsribe` or `lv_msg_subsribe_obj` + */ +void lv_msg_unsubscribe(void * s); + +/** + * Send a message with a given ID and payload + * @param msg_id ID of the message to send + * @param data pointer to the data to send + */ +void lv_msg_send(uint32_t msg_id, const void * payload); + +/** + * Get the ID of a message object. Typically used in the subscriber callback. + * @param m pointer to a message object + * @return the ID of the message + */ +uint32_t lv_msg_get_id(lv_msg_t * m); + +/** + * Get the payload of a message object. Typically used in the subscriber callback. + * @param m pointer to a message object + * @return the payload of the message + */ +const void * lv_msg_get_payload(lv_msg_t * m); + +/** + * Get the user data of a message object. Typically used in the subscriber callback. + * @param m pointer to a message object + * @return the user data of the message + */ +void * lv_msg_get_user_data(lv_msg_t * m); + +/** + * Get the message object from an event object. Can be used in `LV_EVENT_MSG_RECEIVED` events. + * @param e pointer to an event object + * @return the message object or NULL if called with unrelated event code. + */ +lv_msg_t * lv_event_get_msg(lv_event_t * e); + +/********************** + * GLOBAL VARIABLES + **********************/ + +extern lv_event_code_t LV_EVENT_MSG_RECEIVED; + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MSG*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MSG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c index e9fa75109..1b2275115 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c @@ -45,7 +45,9 @@ */ uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf) { + LV_ASSERT_NULL(obj); switch(cf) { + case LV_IMG_CF_TRUE_COLOR: case LV_IMG_CF_TRUE_COLOR_ALPHA: case LV_IMG_CF_ALPHA_1BIT: case LV_IMG_CF_ALPHA_2BIT: @@ -81,10 +83,12 @@ uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf) */ lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size) { - LV_ASSERT(dsc); - LV_ASSERT(buf); + LV_ASSERT_NULL(obj); + LV_ASSERT_NULL(dsc); + LV_ASSERT_NULL(buf); switch(cf) { + case LV_IMG_CF_TRUE_COLOR: case LV_IMG_CF_TRUE_COLOR_ALPHA: case LV_IMG_CF_ALPHA_1BIT: case LV_IMG_CF_ALPHA_2BIT: @@ -124,7 +128,6 @@ lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * lv_memset_00(&fake_disp, sizeof(lv_disp_t)); fake_disp.driver = &driver; - lv_draw_ctx_t * draw_ctx = lv_mem_alloc(obj_disp->driver->draw_ctx_size); LV_ASSERT_MALLOC(draw_ctx); if(draw_ctx == NULL) return LV_RES_INV; @@ -138,7 +141,7 @@ lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); _lv_refr_set_disp_refreshing(&fake_disp); - lv_refr_obj(draw_ctx, obj); + lv_obj_redraw(draw_ctx, obj); _lv_refr_set_disp_refreshing(refr_ori); obj_disp->driver->draw_ctx_deinit(fake_disp.driver, draw_ctx); @@ -160,14 +163,17 @@ lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * */ lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf) { + LV_ASSERT_NULL(obj); uint32_t buff_size = lv_snapshot_buf_size_needed(obj, cf); void * buf = lv_mem_alloc(buff_size); + LV_ASSERT_MALLOC(buf); if(buf == NULL) { return NULL; } lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t)); + LV_ASSERT_MALLOC(buf); if(dsc == NULL) { lv_mem_free(buf); return NULL; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c index fd5bc2d02..d342455ff 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c @@ -16,25 +16,28 @@ /********************* * DEFINES *********************/ - +#define COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) #define COLOR_WHITE lv_color_white() -#define COLOR_LIGHT lv_palette_lighten(LV_PALETTE_GREY, 3) -#define COLOR_MID lv_palette_lighten(LV_PALETTE_GREY, 1) +#define COLOR_LIGHT lv_palette_lighten(LV_PALETTE_GREY, 2) #define COLOR_DARK lv_palette_main(LV_PALETTE_GREY) #define COLOR_DIM lv_palette_darken(LV_PALETTE_GREY, 2) -#define PAD_DEF LV_DPX(5) +#define SCROLLBAR_WIDTH 2 /********************** * TYPEDEFS **********************/ typedef struct { lv_style_t scr; + lv_style_t transp; + lv_style_t white; lv_style_t light; lv_style_t dark; + lv_style_t dim; lv_style_t scrollbar; - lv_style_t pressed; - lv_style_t disabled; - lv_style_t pad_zero; +#if LV_USE_ARC || LV_USE_COLORWHEEL + lv_style_t arc_line; + lv_style_t arc_knob; +#endif #if LV_USE_TEXTAREA lv_style_t ta_cursor; #endif @@ -62,74 +65,60 @@ static bool inited; * STATIC FUNCTIONS **********************/ -static lv_color_t dark_color_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t c, lv_opa_t opa) -{ - LV_UNUSED(f); - return lv_color_darken(c, opa); -} - - -static lv_color_t grey_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t color, lv_opa_t opa) -{ - LV_UNUSED(f); - return lv_color_mix(lv_color_white(), color, opa); -} - static void style_init(void) { style_init_reset(&styles->scrollbar); lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scrollbar, lv_palette_darken(LV_PALETTE_GREY, 2)); - lv_style_set_width(&styles->scrollbar, PAD_DEF); + lv_style_set_bg_color(&styles->scrollbar, COLOR_DARK); + lv_style_set_width(&styles->scrollbar, SCROLLBAR_WIDTH); style_init_reset(&styles->scr); lv_style_set_bg_opa(&styles->scr, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scr, COLOR_WHITE); + lv_style_set_bg_color(&styles->scr, COLOR_SCR); lv_style_set_text_color(&styles->scr, COLOR_DIM); - lv_style_set_pad_row(&styles->scr, PAD_DEF / 2); - lv_style_set_pad_column(&styles->scr, PAD_DEF / 2); + + + style_init_reset(&styles->transp); + lv_style_set_bg_opa(&styles->transp, LV_OPA_TRANSP); + + style_init_reset(&styles->white); + lv_style_set_bg_opa(&styles->white, LV_OPA_COVER); + lv_style_set_bg_color(&styles->white, COLOR_WHITE); + lv_style_set_line_width(&styles->white, 1); + lv_style_set_line_color(&styles->white, COLOR_WHITE); + lv_style_set_arc_width(&styles->white, 2); + lv_style_set_arc_color(&styles->white, COLOR_WHITE); style_init_reset(&styles->light); lv_style_set_bg_opa(&styles->light, LV_OPA_COVER); lv_style_set_bg_color(&styles->light, COLOR_LIGHT); - lv_style_set_border_color(&styles->light, COLOR_MID); - lv_style_set_border_width(&styles->light, 1); - lv_style_set_pad_all(&styles->light, PAD_DEF); - lv_style_set_pad_gap(&styles->light, PAD_DEF / 2); - lv_style_set_line_width(&styles->light, LV_DPX(2)); - lv_style_set_line_color(&styles->light, COLOR_MID); - lv_style_set_arc_width(&styles->light, LV_DPX(2)); - lv_style_set_arc_color(&styles->light, COLOR_MID); + lv_style_set_line_width(&styles->light, 1); + lv_style_set_line_color(&styles->light, COLOR_LIGHT); + lv_style_set_arc_width(&styles->light, 2); + lv_style_set_arc_color(&styles->light, COLOR_LIGHT); style_init_reset(&styles->dark); lv_style_set_bg_opa(&styles->dark, LV_OPA_COVER); lv_style_set_bg_color(&styles->dark, COLOR_DARK); - lv_style_set_border_color(&styles->dark, COLOR_DIM); - lv_style_set_border_width(&styles->dark, 1); - lv_style_set_pad_all(&styles->dark, PAD_DEF); - lv_style_set_pad_gap(&styles->dark, PAD_DEF / 2); - lv_style_set_line_width(&styles->dark, LV_DPX(2)); - lv_style_set_line_color(&styles->dark, COLOR_DIM); - lv_style_set_arc_width(&styles->dark, LV_DPX(2)); - lv_style_set_arc_color(&styles->dark, COLOR_DIM); + lv_style_set_line_width(&styles->dark, 1); + lv_style_set_line_color(&styles->dark, COLOR_DARK); + lv_style_set_arc_width(&styles->dark, 2); + lv_style_set_arc_color(&styles->dark, COLOR_DARK); - static lv_color_filter_dsc_t dark_filter; - lv_color_filter_dsc_init(&dark_filter, dark_color_filter_cb); + style_init_reset(&styles->dim); + lv_style_set_bg_opa(&styles->dim, LV_OPA_COVER); + lv_style_set_bg_color(&styles->dim, COLOR_DIM); + lv_style_set_line_width(&styles->dim, 1); + lv_style_set_line_color(&styles->dim, COLOR_DIM); + lv_style_set_arc_width(&styles->dim, 2); + lv_style_set_arc_color(&styles->dim, COLOR_DIM); - style_init_reset(&styles->pressed); - lv_style_set_color_filter_dsc(&styles->pressed, &dark_filter); - lv_style_set_color_filter_opa(&styles->pressed, 35); - - static lv_color_filter_dsc_t grey_filter; - lv_color_filter_dsc_init(&grey_filter, grey_filter_cb); - - style_init_reset(&styles->disabled); - lv_style_set_color_filter_dsc(&styles->disabled, &grey_filter); - lv_style_set_color_filter_opa(&styles->disabled, LV_OPA_70); - - style_init_reset(&styles->pad_zero); - lv_style_set_pad_all(&styles->pad_zero, 0); - lv_style_set_pad_gap(&styles->pad_zero, 0); +#if LV_USE_ARC || LV_USE_COLORWHEEL + style_init_reset(&styles->arc_line); + lv_style_set_arc_width(&styles->arc_line, 6); + style_init_reset(&styles->arc_knob); + lv_style_set_pad_all(&styles->arc_knob, 5); +#endif #if LV_USE_TEXTAREA style_init_reset(&styles->ta_cursor); @@ -146,15 +135,21 @@ static void style_init(void) * GLOBAL FUNCTIONS **********************/ +bool lv_theme_basic_is_inited(void) +{ + return LV_GC_ROOT(_lv_theme_basic_styles) == NULL ? false : true; +} + lv_theme_t * lv_theme_basic_init(lv_disp_t * disp) { /*This trick is required only to avoid the garbage collection of *styles' data if LVGL is used in a binding (e.g. Micropython) *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ - if(!inited) { - LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); - styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); + if(!lv_theme_basic_is_inited()) { + inited = false; + LV_GC_ROOT(_lv_theme_basic_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); + styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_basic_styles); } theme.disp = disp; @@ -165,9 +160,11 @@ lv_theme_t * lv_theme_basic_init(lv_disp_t * disp) style_init(); - inited = true; + if(disp == NULL || lv_disp_get_theme(disp) == &theme) { + lv_obj_report_style_change(NULL); + } - if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); + inited = true; return (lv_theme_t *)&theme; } @@ -188,12 +185,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); /*Tabview content area*/ if(lv_obj_check_type(parent, &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->scr, 0); return; } /*Tabview pages*/ else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->scr, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); return; } @@ -212,14 +209,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) return; } #endif - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->white, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); } #if LV_USE_BTN else if(lv_obj_check_type(obj, &lv_btn_class)) { lv_obj_add_style(obj, &styles->dark, 0); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); } #endif @@ -228,27 +223,23 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_MSGBOX if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); return; } #endif #if LV_USE_TABVIEW if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); return; } #endif - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->white, 0); + lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); } #endif #if LV_USE_BAR else if(lv_obj_check_type(obj, &lv_bar_class)) { lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); } #endif @@ -256,9 +247,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_SLIDER else if(lv_obj_check_type(obj, &lv_slider_class)) { lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dark, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); } #endif @@ -266,36 +256,30 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) else if(lv_obj_check_type(obj, &lv_table_class)) { lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); } #endif #if LV_USE_CHECKBOX else if(lv_obj_check_type(obj, &lv_checkbox_class)) { lv_obj_add_style(obj, &styles->light, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_INDICATOR | LV_STATE_PRESSED); } #endif #if LV_USE_SWITCH else if(lv_obj_check_type(obj, &lv_switch_class)) { lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dark, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->pad_zero, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); } #endif #if LV_USE_CHART else if(lv_obj_check_type(obj, &lv_chart_class)) { - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->white, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->light, LV_PART_TICKS); - lv_obj_add_style(obj, &styles->light, LV_PART_CURSOR); + lv_obj_add_style(obj, &styles->dark, LV_PART_TICKS); + lv_obj_add_style(obj, &styles->dark, LV_PART_CURSOR); } #endif @@ -308,24 +292,45 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_DROPDOWN else if(lv_obj_check_type(obj, &lv_dropdown_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->white, 0); } else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->white, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->light, LV_PART_SELECTED); lv_obj_add_style(obj, &styles->dark, LV_PART_SELECTED | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_SELECTED | LV_STATE_PRESSED); } #endif #if LV_USE_ARC else if(lv_obj_check_type(obj, &lv_arc_class)) { lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->transp, 0); + lv_obj_add_style(obj, &styles->arc_line, 0); lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->pad_zero, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dark, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->arc_line, LV_PART_INDICATOR); + lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->arc_knob, LV_PART_KNOB); + } +#endif + +#if LV_USE_SPINNER + else if(lv_obj_check_type(obj, &lv_spinner_class)) { + lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->transp, 0); + lv_obj_add_style(obj, &styles->arc_line, 0); + lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); + lv_obj_add_style(obj, &styles->arc_line, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_COLORWHEEL + else if(lv_obj_check_type(obj, &lv_colorwheel_class)) { + lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->transp, 0); + lv_obj_add_style(obj, &styles->arc_line, 0); + lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->arc_knob, LV_PART_KNOB); } #endif @@ -337,27 +342,23 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_TEXTAREA else if(lv_obj_check_type(obj, &lv_textarea_class)) { - lv_obj_add_style(obj, &styles->light, 0); + lv_obj_add_style(obj, &styles->white, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->ta_cursor, LV_PART_CURSOR); - lv_obj_add_style(obj, &styles->light, LV_PART_TEXTAREA_PLACEHOLDER); + lv_obj_add_style(obj, &styles->ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); } #endif #if LV_USE_CALENDAR else if(lv_obj_check_type(obj, &lv_calendar_class)) { lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); } #endif #if LV_USE_KEYBOARD else if(lv_obj_check_type(obj, &lv_keyboard_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->scr, 0); + lv_obj_add_style(obj, &styles->white, LV_PART_ITEMS); + lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS | LV_STATE_CHECKED); } #endif #if LV_USE_LIST @@ -371,7 +372,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) } else if(lv_obj_check_type(obj, &lv_list_btn_class)) { lv_obj_add_style(obj, &styles->dark, 0); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); } #endif @@ -417,8 +417,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) static void style_init_reset(lv_style_t * style) { - if(inited) lv_style_reset(style); - else lv_style_init(style); + if(inited) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h index e47ed79ee..93a8fa841 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h @@ -36,6 +36,12 @@ extern "C" { */ lv_theme_t * lv_theme_basic_init(lv_disp_t * disp); +/** +* Check if the theme is initialized +* @return true if default theme is initialized, false otherwise +*/ +bool lv_theme_basic_is_inited(void); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c index 479dba47f..47392b0d1 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c @@ -125,6 +125,11 @@ typedef struct { lv_style_t colorwheel_main; #endif +#if LV_USE_MENU + lv_style_t menu_bg, menu_cont, menu_sidebar_cont, menu_main_cont, menu_page, menu_header_cont, menu_header_btn, + menu_section, menu_pressed, menu_separator; +#endif + #if LV_USE_MSGBOX lv_style_t msgbox_bg, msgbox_btn_bg, msgbox_backdrop_bg; #endif @@ -168,11 +173,11 @@ static void style_init_reset(lv_style_t * style); static my_theme_styles_t * styles; static lv_theme_t theme; static disp_size_t disp_size; -static bool inited; static lv_color_t color_scr; static lv_color_t color_text; static lv_color_t color_card; static lv_color_t color_grey; +static bool inited = false; /********************** @@ -213,27 +218,32 @@ static void style_init(void) color_card = theme.flags & MODE_DARK ? DARK_COLOR_CARD : LIGHT_COLOR_CARD; color_grey = theme.flags & MODE_DARK ? DARK_COLOR_GREY : LIGHT_COLOR_GREY; + style_init_reset(&styles->transition_delayed); + style_init_reset(&styles->transition_normal); +#if TRANSITION_TIME static lv_style_transition_dsc_t trans_delayed; lv_style_transition_dsc_init(&trans_delayed, trans_props, lv_anim_path_linear, TRANSITION_TIME, 70, NULL); static lv_style_transition_dsc_t trans_normal; lv_style_transition_dsc_init(&trans_normal, trans_props, lv_anim_path_linear, TRANSITION_TIME, 0, NULL); - style_init_reset(&styles->transition_delayed); lv_style_set_transition(&styles->transition_delayed, &trans_delayed); /*Go back to default state with delay*/ - style_init_reset(&styles->transition_normal); lv_style_set_transition(&styles->transition_normal, &trans_normal); /*Go back to default state with delay*/ +#endif style_init_reset(&styles->scrollbar); - lv_style_set_bg_color(&styles->scrollbar, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, - 2) : lv_palette_main(LV_PALETTE_GREY)); + lv_color_t sb_color = (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, + 2) : lv_palette_main(LV_PALETTE_GREY); + lv_style_set_bg_color(&styles->scrollbar, sb_color); + lv_style_set_radius(&styles->scrollbar, LV_RADIUS_CIRCLE); - lv_style_set_pad_right(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); - lv_style_set_pad_top(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); - lv_style_set_size(&styles->scrollbar, lv_disp_dpx(theme.disp, 5)); + lv_style_set_pad_all(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); + lv_style_set_width(&styles->scrollbar, lv_disp_dpx(theme.disp, 5)); lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_40); +#if TRANSITION_TIME lv_style_set_transition(&styles->scrollbar, &trans_normal); +#endif style_init_reset(&styles->scrollbar_scrolled); lv_style_set_bg_opa(&styles->scrollbar_scrolled, LV_OPA_COVER); @@ -454,6 +464,67 @@ static void style_init(void) lv_style_set_text_color(&styles->chart_ticks, lv_palette_main(LV_PALETTE_GREY)); #endif +#if LV_USE_MENU + style_init_reset(&styles->menu_bg); + lv_style_set_pad_all(&styles->menu_bg, 0); + lv_style_set_pad_gap(&styles->menu_bg, 0); + lv_style_set_radius(&styles->menu_bg, 0); + lv_style_set_clip_corner(&styles->menu_bg, true); + lv_style_set_border_side(&styles->menu_bg, LV_BORDER_SIDE_NONE); + + style_init_reset(&styles->menu_section); + lv_style_set_radius(&styles->menu_section, RADIUS_DEFAULT); + lv_style_set_clip_corner(&styles->menu_section, true); + lv_style_set_bg_opa(&styles->menu_section, LV_OPA_COVER); + lv_style_set_bg_color(&styles->menu_section, color_card); + lv_style_set_text_color(&styles->menu_section, color_text); + + style_init_reset(&styles->menu_cont); + lv_style_set_pad_hor(&styles->menu_cont, PAD_SMALL); + lv_style_set_pad_ver(&styles->menu_cont, PAD_SMALL); + lv_style_set_pad_gap(&styles->menu_cont, PAD_SMALL); + lv_style_set_border_width(&styles->menu_cont, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_opa(&styles->menu_cont, LV_OPA_10); + lv_style_set_border_color(&styles->menu_cont, color_text); + lv_style_set_border_side(&styles->menu_cont, LV_BORDER_SIDE_NONE); + + style_init_reset(&styles->menu_sidebar_cont); + lv_style_set_pad_all(&styles->menu_sidebar_cont, 0); + lv_style_set_pad_gap(&styles->menu_sidebar_cont, 0); + lv_style_set_border_width(&styles->menu_sidebar_cont, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_opa(&styles->menu_sidebar_cont, LV_OPA_10); + lv_style_set_border_color(&styles->menu_sidebar_cont, color_text); + lv_style_set_border_side(&styles->menu_sidebar_cont, LV_BORDER_SIDE_RIGHT); + + style_init_reset(&styles->menu_main_cont); + lv_style_set_pad_all(&styles->menu_main_cont, 0); + lv_style_set_pad_gap(&styles->menu_main_cont, 0); + + style_init_reset(&styles->menu_header_cont); + lv_style_set_pad_hor(&styles->menu_header_cont, PAD_SMALL); + lv_style_set_pad_ver(&styles->menu_header_cont, PAD_TINY); + lv_style_set_pad_gap(&styles->menu_header_cont, PAD_SMALL); + + style_init_reset(&styles->menu_header_btn); + lv_style_set_pad_hor(&styles->menu_header_btn, PAD_TINY); + lv_style_set_pad_ver(&styles->menu_header_btn, PAD_TINY); + lv_style_set_shadow_opa(&styles->menu_header_btn, LV_OPA_TRANSP); + lv_style_set_bg_opa(&styles->menu_header_btn, LV_OPA_TRANSP); + lv_style_set_text_color(&styles->menu_header_btn, color_text); + + style_init_reset(&styles->menu_page); + lv_style_set_pad_hor(&styles->menu_page, 0); + lv_style_set_pad_gap(&styles->menu_page, 0); + + style_init_reset(&styles->menu_pressed); + lv_style_set_bg_opa(&styles->menu_pressed, LV_OPA_20); + lv_style_set_bg_color(&styles->menu_pressed, lv_palette_main(LV_PALETTE_GREY)); + + style_init_reset(&styles->menu_separator); + lv_style_set_bg_opa(&styles->menu_separator, LV_OPA_TRANSP); + lv_style_set_pad_ver(&styles->menu_separator, PAD_TINY); +#endif + #if LV_USE_METER style_init_reset(&styles->meter_marker); lv_style_set_line_width(&styles->meter_marker, lv_disp_dpx(theme.disp, 5)); @@ -581,7 +652,8 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l /*This trick is required only to avoid the garbage collection of *styles' data if LVGL is used in a binding (e.g. Micropython) *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ - if(!inited) { + if(!lv_theme_default_is_inited()) { + inited = false; LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); } @@ -601,23 +673,25 @@ lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, l style_init(); - inited = true; - if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); + inited = true; + return (lv_theme_t *)&theme; } lv_theme_t * lv_theme_default_get(void) { - if(!inited) return NULL; + if(!lv_theme_default_is_inited()) { + return NULL; + } return (lv_theme_t *)&theme; } bool lv_theme_default_is_inited(void) { - return inited; + return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true; } @@ -667,10 +741,10 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_CALENDAR - else if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { - /*No style*/ - return; - } + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + /*No style*/ + return; + } #endif lv_obj_add_style(obj, &styles->card, 0); @@ -690,6 +764,14 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #endif lv_obj_add_style(obj, &styles->bg_color_secondary, LV_STATE_CHECKED); lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); + +#if LV_USE_MENU + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_sidebar_header_cont_class) || + lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_main_header_cont_class)) { + lv_obj_add_style(obj, &styles->menu_header_btn, 0); + lv_obj_add_style(obj, &styles->menu_pressed, LV_STATE_PRESSED); + } +#endif } #endif @@ -917,6 +999,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) else if(lv_obj_check_type(obj, &lv_textarea_class)) { lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->pad_small, 0); + lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); @@ -983,6 +1066,44 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) } #endif +#if LV_USE_MENU + else if(lv_obj_check_type(obj, &lv_menu_class)) { + lv_obj_add_style(obj, &styles->card, 0); + lv_obj_add_style(obj, &styles->menu_bg, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_sidebar_cont_class)) { + lv_obj_add_style(obj, &styles->menu_sidebar_cont, 0); + lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_main_cont_class)) { + lv_obj_add_style(obj, &styles->menu_main_cont, 0); + lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_cont_class)) { + lv_obj_add_style(obj, &styles->menu_cont, 0); + lv_obj_add_style(obj, &styles->menu_pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_STATE_PRESSED | LV_STATE_CHECKED); + lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_STATE_CHECKED); + lv_obj_add_style(obj, &styles->bg_color_primary, LV_STATE_FOCUS_KEY); + } + else if(lv_obj_check_type(obj, &lv_menu_sidebar_header_cont_class) || + lv_obj_check_type(obj, &lv_menu_main_header_cont_class)) { + lv_obj_add_style(obj, &styles->menu_header_cont, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_page_class)) { + lv_obj_add_style(obj, &styles->menu_page, 0); + lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_section_class)) { + lv_obj_add_style(obj, &styles->menu_section, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_separator_class)) { + lv_obj_add_style(obj, &styles->menu_separator, 0); + } +#endif #if LV_USE_MSGBOX else if(lv_obj_check_type(obj, &lv_msgbox_class)) { lv_obj_add_style(obj, &styles->card, 0); @@ -1049,8 +1170,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) static void style_init_reset(lv_style_t * style) { - if(inited) lv_style_reset(style); - else lv_style_init(style); + if(inited) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c index 637564274..b249e76d5 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c @@ -164,6 +164,11 @@ static void style_init(bool dark_bg, const lv_font_t * font) * GLOBAL FUNCTIONS **********************/ +bool lv_theme_mono_is_inited(void) +{ + return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true; +} + lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) { @@ -171,6 +176,7 @@ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t *styles' data if LVGL is used in a binding (e.g. Micropython) *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ if(!inited) { + inited = false; LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); } @@ -183,10 +189,10 @@ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t style_init(dark_bg, font); - inited = true; - if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); + inited = true; + return (lv_theme_t *)&theme; } @@ -487,8 +493,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) static void style_init_reset(lv_style_t * style) { - if(inited) lv_style_reset(style); - else lv_style_init(style); + if(inited) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h index 789623a27..10b8f186d 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h @@ -38,6 +38,12 @@ extern "C" { */ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font); +/** +* Check if the theme is initialized +* @return true if default theme is initialized, false otherwise +*/ +bool lv_theme_mono_is_inited(void); + /********************** * MACROS **********************/ @@ -48,4 +54,4 @@ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t } /*extern "C"*/ #endif -#endif /*LV_THEME_DEFAULT_H*/ +#endif /*LV_USE_THEME_MONO_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c index f469eae5c..b806d2529 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c @@ -120,7 +120,7 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) d.month = calendar->showed_date.month; d.day = calendar->showed_date.day; - uint8_t i; + uint32_t i; /*Remove the disabled state but revert it for day names*/ lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_DISABLED); @@ -262,7 +262,7 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o if(i != 0 && (i + 1) % 8 == 0) { calendar->map[i] = "\n"; } - else if(i < 8) { + else if(i < 7) { calendar->map[i] = day_names_def[i]; } else { diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c index a6e09fb45..da6c18c0e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c @@ -539,7 +539,6 @@ void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t invalidate_point(obj, ser->start_point); ser->start_point = (ser->start_point + 1) % chart->point_cnt; invalidate_point(obj, ser->start_point); - lv_chart_refresh(obj); } void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value) @@ -556,11 +555,8 @@ void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_ ser->x_points[ser->start_point] = x_value; ser->y_points[ser->start_point] = y_value; - invalidate_point(obj, ser->start_point); ser->start_point = (ser->start_point + 1) % chart->point_cnt; invalidate_point(obj, ser->start_point); - lv_chart_refresh(obj); - } void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t value) @@ -571,7 +567,7 @@ void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t if(id >= chart->point_cnt) return; ser->y_points[id] = value; - lv_chart_refresh(obj); + invalidate_point(obj, id); } void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, @@ -589,7 +585,7 @@ void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t if(id >= chart->point_cnt) return; ser->x_points[id] = x_value; ser->y_points[id] = y_value; - lv_chart_refresh(obj); + invalidate_point(obj, id); } void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]) @@ -720,7 +716,7 @@ static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e) p.x -= obj->coords.x1; uint32_t id = get_index_from_x(obj, p.x + lv_obj_get_scroll_left(obj)); - if(id != chart->pressed_point_id) { + if(id != (uint32_t)chart->pressed_point_id) { invalidate_point(obj, id); invalidate_point(obj, chart->pressed_point_id); chart->pressed_point_id = id; @@ -908,7 +904,7 @@ static void draw_series_line(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) if(LV_MIN(point_w, point_h) > line_dsc_default.width / 2) line_dsc_default.raw_end = 1; if(line_dsc_default.width == 1) line_dsc_default.raw_end = 1; - /*If there are mire points than pixels draw only vertical lines*/ + /*If there are at least as much points as pixels then draw only vertical lines*/ bool crowded_mode = chart->point_cnt >= w ? true : false; /*Go through all data lines*/ @@ -1201,11 +1197,13 @@ static void draw_series_bar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ lv_coord_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; - lv_coord_t col_w = block_w / ser_cnt; int32_t ser_gap = ((int32_t)lv_obj_get_style_pad_column(obj, - LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the column on the ~same X*/ - lv_coord_t x_ofs = pad_left - lv_obj_get_scroll_left(obj); - lv_coord_t y_ofs = pad_top - lv_obj_get_scroll_top(obj); + LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the columns on the ~same X*/ + lv_coord_t col_w = (block_w - (ser_cnt - 1) * ser_gap) / ser_cnt; + + lv_coord_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + lv_coord_t x_ofs = pad_left - lv_obj_get_scroll_left(obj) + border_w; + lv_coord_t y_ofs = pad_top - lv_obj_get_scroll_top(obj) + border_w; lv_draw_rect_dsc_t col_dsc; lv_draw_rect_dsc_init(&col_dsc); @@ -1224,7 +1222,7 @@ static void draw_series_bar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /*Go through all points*/ for(i = 0; i < chart->point_cnt; i++) { - lv_coord_t x_act = (int32_t)((int32_t)(w + block_gap) * i) / (chart->point_cnt) + obj->coords.x1 + x_ofs; + lv_coord_t x_act = (int32_t)((int32_t)(w - block_w) * i) / (chart->point_cnt - 1) + obj->coords.x1 + x_ofs; part_draw_dsc.id = i; @@ -1234,8 +1232,8 @@ static void draw_series_bar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) lv_coord_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; col_a.x1 = x_act; - col_a.x2 = col_a.x1 + col_w - ser_gap - 1; - x_act += col_w; + col_a.x2 = col_a.x1 + col_w - 1; + x_act += col_w + ser_gap; if(col_a.x2 < clip_area.x1) continue; if(col_a.x1 > clip_area.x2) break; @@ -1329,7 +1327,8 @@ static void draw_cursors(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) cy += obj->coords.y1; lv_area_t point_area; - if(point_w && point_h) { + bool draw_point = point_w && point_h; + if(draw_point) { point_area.x1 = cx - point_w; point_area.x2 = cx + point_w; point_area.y1 = cy - point_h; @@ -1349,7 +1348,11 @@ static void draw_cursors(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(draw_ctx, &line_dsc_tmp, &p1, &p2); - lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); + + if(draw_point) { + lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); + } + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } @@ -1361,7 +1364,11 @@ static void draw_cursors(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_line(draw_ctx, &line_dsc_tmp, &p1, &p2); - lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); + + if(draw_point) { + lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); + } + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } } @@ -1515,7 +1522,6 @@ static void draw_x_ticks(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_chart_axis lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_draw_label_dsc_t label_dsc; lv_draw_label_dsc_init(&label_dsc); lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); @@ -1559,6 +1565,7 @@ static void draw_x_ticks(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_chart_axis int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the columns on ~adjacent X*/ lv_coord_t block_w = (w + block_gap) / (chart->point_cnt); + x_ofs += (block_w - block_gap) / 2; w -= block_w - block_gap; } @@ -1708,11 +1715,13 @@ static void invalidate_point(lv_obj_t * obj, uint16_t i) lv_area_t col_a; int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ + lv_coord_t block_w = (w + block_gap) / chart->point_cnt; + lv_coord_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t x_act; x_act = (int32_t)((int32_t)(block_w) * i) ; - x_act += obj->coords.x1 + lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + x_act += obj->coords.x1 + bwidth + lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_obj_get_coords(obj, &col_a); col_a.x1 = x_act - scroll_left; @@ -1721,9 +1730,6 @@ static void invalidate_point(lv_obj_t * obj, uint16_t i) lv_obj_invalidate_area(obj, &col_a); } - else if(chart->type == LV_CHART_TYPE_SCATTER) { - lv_obj_invalidate(obj); - } else { lv_obj_invalidate(obj); } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h index 8a9b8cfc0..394c0e7b0 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h @@ -22,7 +22,11 @@ extern "C" { *********************/ /**Default value of points. Can be used to not draw a point*/ +#if LV_USE_LARGE_COORD +#define LV_CHART_POINT_NONE (INT32_MAX) +#else #define LV_CHART_POINT_NONE (INT16_MAX) +#endif LV_EXPORT_CONST_INT(LV_CHART_POINT_NONE); /********************** @@ -78,7 +82,7 @@ typedef struct { typedef struct { lv_point_t pos; - uint16_t point_id; + lv_coord_t point_id; lv_color_t color; lv_chart_series_t * ser; lv_dir_t dir; @@ -104,7 +108,7 @@ typedef struct { lv_coord_t ymax[2]; lv_coord_t xmin[2]; lv_coord_t xmax[2]; - uint16_t pressed_point_id; + lv_coord_t pressed_point_id; uint16_t hdiv_cnt; /**< Number of horizontal division lines*/ uint16_t vdiv_cnt; /**< Number of vertical division lines*/ uint16_t point_cnt; /**< Point number in a data line*/ @@ -339,7 +343,7 @@ void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_po * @param obj pointer to a chart object * @param cursor pointer to the cursor * @param ser pointer to a series - * @param point_id the point's index or `LV_CHART_POINT_NONE` to not assign to any points. + * @param point_id the point's index or `LV_CHART_POINT_NONE` to not assign to any points. */ void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint16_t point_id); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c index 6ba431eb9..8e052e33a 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c @@ -285,19 +285,19 @@ void lv_keyboard_def_event_cb(lv_event_t * e) if(strcmp(txt, "abc") == 0) { keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER; lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_TEXT_LOWER]); + lv_keyboard_update_ctrl_map(obj); return; } else if(strcmp(txt, "ABC") == 0) { keyboard->mode = LV_KEYBOARD_MODE_TEXT_UPPER; lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_TEXT_UPPER]); + lv_keyboard_update_ctrl_map(obj); return; } else if(strcmp(txt, "1#") == 0) { keyboard->mode = LV_KEYBOARD_MODE_SPECIAL; lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]); - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_SPECIAL]); + lv_keyboard_update_ctrl_map(obj); return; } else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0 || strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c index ea9ced729..29355fd3c 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c @@ -73,7 +73,7 @@ lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) return obj; } -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const char * icon, const char * txt) +lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) { LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_btn_class, list); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h index 8b9164415..0da5595bc 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h @@ -37,7 +37,7 @@ lv_obj_t * lv_list_create(lv_obj_t * parent); lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt); -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const char * icon, const char * txt); +lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt); const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c index 9c6b5423a..78577e770 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c @@ -124,7 +124,15 @@ lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char * title) lv_obj_class_init_obj(obj); lv_menu_page_t * page = (lv_menu_page_t *)obj; - page->title = title; + if(title) { + page->title = lv_mem_alloc(strlen(title) + 1); + LV_ASSERT_MALLOC(page->title); + if(page->title == NULL) return NULL; + strcpy(page->title, title); + } + else { + page->title = NULL; + } return obj; } @@ -196,6 +204,7 @@ void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page) /* Add a new node */ lv_ll_t * history_ll = &(menu->history_ll); lv_menu_history_t * new_node = _lv_ll_ins_head(history_ll); + LV_ASSERT_MALLOC(new_node); new_node->page = page; menu->cur_depth++; @@ -352,8 +361,9 @@ void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * pag { LV_ASSERT_OBJ(menu, MY_CLASS); - /* Make the object clickable */ lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /* Remove old event */ if(lv_obj_remove_event_cb(obj, lv_menu_load_page_event_cb)) { @@ -675,6 +685,11 @@ static void lv_menu_load_page_event_cb(lv_event_t * e) } lv_menu_set_page((lv_obj_t *)menu, page); + + if(lv_group_get_default() != NULL && menu->sidebar_page == NULL) { + /* Sidebar is not supported for now*/ + lv_group_focus_next(lv_group_get_default()); + } } static void lv_menu_obj_del_event_cb(lv_event_t * e) diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c index c12dc33c9..668ab97e9 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c @@ -379,8 +379,6 @@ static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, cons p_center.x = scale_area->x1 + r_edge; p_center.y = scale_area->y1 + r_edge; - uint8_t i; - lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(obj, LV_PART_TICKS, &line_dsc); @@ -406,7 +404,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, cons _LV_LL_READ_BACK(&meter->scale_ll, scale) { part_draw_dsc.sub_part_ptr = scale; - lv_coord_t r_out = r_edge + scale->r_mod; + lv_coord_t r_out = r_edge; lv_coord_t r_in_minor = r_out - scale->tick_length; lv_coord_t r_in_major = r_out - scale->tick_major_length; @@ -435,6 +433,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, cons int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/ uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF; + uint16_t i; for(i = 0; i < scale->tick_cnt; i++) { minor_cnt++; bool major = false; @@ -474,32 +473,20 @@ static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, cons } } - /*`* 256` for extra precision*/ - int32_t angle_upscale = ((i * scale->angle_range) << 8) / (scale->tick_cnt - 1); - - int32_t angle_low = (angle_upscale >> 8); - int32_t angle_high = angle_low + 1; - int32_t angle_rem = angle_upscale & 0xFF; - - /*Interpolate sine and cos*/ - int32_t sin_low = lv_trigo_sin(angle_low + scale->rotation); - int32_t sin_high = lv_trigo_sin(angle_high + scale->rotation); - int32_t sin_mid = (sin_low * (256 - angle_rem) + sin_high * angle_rem) >> 8; - - int32_t cos_low = lv_trigo_cos(angle_low + scale->rotation); - int32_t cos_high = lv_trigo_cos(angle_high + scale->rotation); - int32_t cos_mid = (cos_low * (256 - angle_rem) + cos_high * angle_rem) >> 8; + int32_t angle_upscale = ((i * scale->angle_range) * 10) / (scale->tick_cnt - 1) + + scale->rotation * 10; line_dsc.color = line_color; line_dsc.width = line_width; - /*Use the interpolated angle to get the outer x and y coordinates. - *Draw a little bit longer lines to be sure the mask will clip them correctly*/ - lv_point_t p_outer; - p_outer.x = (int32_t)(((int32_t)cos_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.x; - p_outer.y = (int32_t)(((int32_t)sin_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.y; - part_draw_dsc.p1 = &p_outer; + /*Draw a little bit longer lines to be sure the mask will clip them correctly + *and to get a better precision*/ + lv_point_t p_outer; + p_outer.x = p_center.x + r_out + LV_MAX(LV_DPI_DEF, r_out); + p_outer.y = p_center.y; + lv_point_transform(&p_outer, angle_upscale, 256, &p_center); + part_draw_dsc.p1 = &p_center; + part_draw_dsc.p2 = &p_outer; part_draw_dsc.id = i; part_draw_dsc.label_dsc = &label_dsc; @@ -508,8 +495,9 @@ static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, cons lv_draw_mask_remove_id(outer_mask_id); uint32_t r_text = r_in_major - scale->label_gap; lv_point_t p; - p.x = (int32_t)((int32_t)((int32_t)cos_mid * r_text + 127) >> LV_TRIGO_SHIFT) + p_center.x; - p.y = (int32_t)((int32_t)((int32_t)sin_mid * r_text + 127) >> LV_TRIGO_SHIFT) + p_center.y; + p.x = p_center.x + r_text; + p.y = p_center.y; + lv_point_transform(&p, angle_upscale, 256, &p_center); lv_draw_label_dsc_t label_dsc_tmp; lv_memcpy(&label_dsc_tmp, &label_dsc, sizeof(label_dsc_tmp)); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c index a62c9ae63..8db5df7ee 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c @@ -74,8 +74,8 @@ lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * lv_obj_t * obj = lv_obj_class_create_obj(&lv_msgbox_class, parent); LV_ASSERT_MALLOC(obj); - lv_obj_class_init_obj(obj); if(obj == NULL) return NULL; + lv_obj_class_init_obj(obj); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c index 4bba67611..96f044760 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c @@ -209,6 +209,14 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode) lv_spangroup_refr_mode(obj); } +void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spangroup_t * spans = (lv_spangroup_t *)obj; + spans->lines = lines; + lv_spangroup_refr_mode(obj); +} + /*===================== * Getter functions *====================*/ @@ -289,6 +297,13 @@ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj) return spans->mode; } +int32_t lv_spangroup_get_lines(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_spangroup_t * spans = (lv_spangroup_t *)obj; + return spans->lines; +} + void lv_spangroup_refr_mode(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -400,6 +415,8 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) lv_snippet_t snippet; /* use to save cur_span info and push it to stack */ memset(&snippet, 0, sizeof(snippet)); + int32_t line_cnt = 0; + int32_t lines = spans->lines < 0 ? INT32_MAX : spans->lines; /* the loop control how many lines need to draw */ while(cur_span) { int snippet_cnt = 0; @@ -467,6 +484,10 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) txt_pos.x = 0; txt_pos.y += max_line_h; max_w = max_width; + line_cnt += 1; + if(line_cnt >= lines) { + break; + } } txt_pos.y -= line_space; @@ -483,6 +504,7 @@ static void lv_spangroup_constructor(const lv_obj_class_t * class_p, lv_obj_t * lv_spangroup_t * spans = (lv_spangroup_t *)obj; _lv_ll_init(&spans->child_ll, sizeof(lv_span_t)); spans->indent = 0; + spans->lines = -1; spans->mode = LV_SPAN_MODE_EXPAND; spans->overflow = LV_SPAN_OVERFLOW_CLIP; spans->cache_w = 0; @@ -780,6 +802,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) bool is_end_line = false; bool ellipsis_valid = false; lv_coord_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ + lv_coord_t max_baseline = 0; /*baseline of the highest span*/ lv_snippet_clear(); /* the loop control to find a line and push the relevant span info into stack */ @@ -803,15 +826,6 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) snippet.line_h = lv_font_get_line_height(snippet.font) + line_space; } - if(spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS) { - /* curretn line span txt overflow, don't push */ - if(txt_pos.y + snippet.line_h - line_space > coords.y2 + 1) { - ellipsis_valid = true; - is_end_line = true; - break; - } - } - /* get current span text line info */ uint32_t next_ofs = 0; lv_coord_t use_width = 0; @@ -819,24 +833,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) max_w, txt_flag, &use_width, &next_ofs); if(isfill) { - lv_coord_t next_line_h = snippet.line_h; - if(cur_txt[cur_txt_ofs + next_ofs] == '\0') { - next_line_h = 0; - lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, cur_span); - if(next_span) { /* have the next line */ - next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space; - } - } - lv_coord_t cur_line_h = max_line_h < snippet.line_h ? snippet.line_h : max_line_h; - if(txt_pos.y + cur_line_h + next_line_h - line_space > coords.y2 + 1) { /* for overflow if is end line. */ - if(cur_txt[cur_txt_ofs + next_ofs] != '\0') { - next_ofs = strlen(&cur_txt[cur_txt_ofs]); - use_width = lv_txt_get_width(&cur_txt[cur_txt_ofs], next_ofs, snippet.font, snippet.letter_space, txt_flag); - ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false; - is_end_line = true; - } - } - else if(next_ofs > 0 && lv_get_snippet_cnt() > 0) { + if(next_ofs > 0 && lv_get_snippet_cnt() > 0) { /* To prevent infinite loops, the _lv_txt_get_next_line() may return incomplete words, */ /* This phenomenon should be avoided when lv_get_snippet_cnt() > 0 */ if(max_w < use_width) { @@ -860,6 +857,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) cur_txt_ofs += next_ofs; if(max_line_h < snippet.line_h) { max_line_h = snippet.line_h; + max_baseline = snippet.font->base_line; } lv_snippet_push(&snippet); @@ -869,13 +867,35 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) } } - /* start current line deal width */ + /* start current line deal with */ uint16_t item_cnt = lv_get_snippet_cnt(); if(item_cnt == 0) { /* break if stack is empty */ break; } + /* Whether the current line is the end line and does overflow processing */ + { + lv_snippet_t * last_snippet = lv_get_snippet(item_cnt - 1); + lv_coord_t next_line_h = last_snippet->line_h; + if(last_snippet->txt[last_snippet->bytes] == '\0') { + next_line_h = 0; + lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, last_snippet->span); + if(next_span) { /* have the next line */ + next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space; + } + } + if(txt_pos.y + max_line_h + next_line_h - line_space > coords.y2 + 1) { /* for overflow if is end line. */ + if(last_snippet->txt[last_snippet->bytes] != '\0') { + last_snippet->bytes = strlen(last_snippet->txt); + last_snippet->txt_w = lv_txt_get_width(last_snippet->txt, last_snippet->bytes, last_snippet->font, + last_snippet->letter_space, txt_flag); + } + ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false; + is_end_line = true; + } + } + /*Go the first visible line*/ if(txt_pos.y + max_line_h < clip_area.y1) { goto Next_line_init; @@ -908,7 +928,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) lv_point_t pos; pos.x = txt_pos.x; - pos.y = txt_pos.y + max_line_h - pinfo->line_h; + pos.y = txt_pos.y + max_line_h - pinfo->line_h - (max_baseline - pinfo->font->base_line); label_draw_dsc.color = lv_span_get_style_text_color(obj, pinfo->span); label_draw_dsc.opa = lv_span_get_style_text_opa(obj, pinfo->span); label_draw_dsc.font = lv_span_get_style_text_font(obj, pinfo->span); @@ -963,13 +983,6 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) } } - if(ellipsis_valid && i == item_cnt - 1 && pos.x <= ellipsis_width) { - for(int ell = 0; ell < 3; ell++) { - lv_draw_letter(draw_ctx, &label_draw_dsc, &pos, '.'); - pos.x = pos.x + dot_letter_w + pinfo->letter_space; - } - } - /* draw decor */ lv_text_decor_t decor = lv_span_get_style_text_decor(obj, pinfo->span); if(decor != LV_TEXT_DECOR_NONE) { @@ -1021,8 +1034,8 @@ static void refresh_self_size(lv_obj_t * obj) { lv_spangroup_t * spans = (lv_spangroup_t *)obj; spans->refresh = 1; - lv_obj_refresh_self_size(obj); lv_obj_invalidate(obj); + lv_obj_refresh_self_size(obj); } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h index 418ad87e2..f00d04db7 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h @@ -50,6 +50,7 @@ typedef struct { /** Data of label*/ typedef struct { lv_obj_t obj; + int32_t lines; lv_coord_t indent; /* first line indent */ lv_coord_t cache_w; /* the cache automatically calculates the width */ lv_coord_t cache_h; /* similar cache_w */ @@ -133,6 +134,13 @@ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent); */ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode); +/** + * Set lines of the spangroup. + * @param obj pointer to a spangroup object. + * @param lines max lines that can be displayed in LV_SPAN_MODE_BREAK mode. < 0 means no limit. + */ +void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines); + /*===================== * Getter functions *====================*/ @@ -185,6 +193,13 @@ lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj); */ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj); +/** + * get lines of the spangroup. + * @param obj pointer to a spangroup object. + * @return the lines value. + */ +int32_t lv_spangroup_get_lines(lv_obj_t * obj); + /** * get max line height of all span in the spangroup. * @param obj pointer to a spangroup object. diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c index 72aca7db8..34691053e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c @@ -34,6 +34,7 @@ static void lv_spinbox_updatevalue(lv_obj_t * obj); const lv_obj_class_t lv_spinbox_class = { .constructor_cb = lv_spinbox_constructor, .event_cb = lv_spinbox_event, + .width_def = LV_DPI_DEF, .instance_size = sizeof(lv_spinbox_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, .base_class = &lv_textarea_class @@ -104,7 +105,6 @@ void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t se if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT) digit_count = LV_SPINBOX_MAX_DIGIT_COUNT; if(separator_position >= digit_count) separator_position = 0; - if(separator_position > LV_SPINBOX_MAX_DIGIT_COUNT) separator_position = LV_SPINBOX_MAX_DIGIT_COUNT; if(digit_count < LV_SPINBOX_MAX_DIGIT_COUNT) { int64_t max_val = lv_pow(10, digit_count); @@ -157,7 +157,7 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) * @param spinbox pointer to spinbox * @param pos selected position in spinbox */ -void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos) +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; @@ -336,7 +336,6 @@ static void lv_spinbox_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_textarea_set_one_line(obj, true); lv_textarea_set_cursor_click_pos(obj, true); - lv_obj_set_width(obj, LV_DPI_DEF); lv_spinbox_updatevalue(obj); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h index 14c73ba36..1a4bc322f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h @@ -105,7 +105,7 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); * @param obj pointer to spinbox * @param pos selected position in spinbox */ -void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos); +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos); /** * Set direction of digit step when clicking an encoder button while in editing mode @@ -170,6 +170,10 @@ void lv_spinbox_decrement(lv_obj_t * obj); * MACROS **********************/ +/* It was ambiguous in MicroPython. See https://github.com/lvgl/lvgl/issues/3301 + * TODO remove in v9*/ +#define lv_spinbox_set_pos lv_spinbox_set_cursor_pos + #endif /*LV_USE_SPINBOX*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c old mode 100644 new mode 100755 index 8ccd143e1..81addc663 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c @@ -121,6 +121,20 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) return page; } +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t id, const char * new_name) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + + if(id >= tabview->tab_cnt) return; + if(tabview->tab_pos & LV_DIR_HOR) id *= 2; + + lv_mem_free(tabview->map[id]); + tabview->map[id] = lv_mem_alloc(strlen(new_name) + 1); + strcpy(tabview->map[id], new_name); + lv_obj_invalidate(obj); +} + void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -135,14 +149,22 @@ void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) lv_obj_t * cont = lv_tabview_get_content(obj); if(cont == NULL) return; - lv_coord_t gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_content_width(cont); - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { - lv_obj_scroll_to_x(cont, id * (gap + w), anim_en); + + if((tabview->tab_pos & LV_DIR_VER) != 0) { + lv_coord_t gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); + lv_coord_t w = lv_obj_get_content_width(cont); + if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { + lv_obj_scroll_to_x(cont, id * (gap + w), anim_en); + } + else { + int32_t id_rtl = -(int32_t)id; + lv_obj_scroll_to_x(cont, (gap + w) * id_rtl, anim_en); + } } else { - int32_t id_rtl = -(int32_t)id; - lv_obj_scroll_to_x(cont, (gap + w) * id_rtl, anim_en); + lv_coord_t gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + lv_coord_t h = lv_obj_get_content_height(cont); + lv_obj_scroll_to_y(cont, id * (gap + h), anim_en); } lv_obj_t * btns = lv_tabview_get_tab_btns(obj); @@ -229,8 +251,14 @@ static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_group_t * g = lv_group_get_default(); if(g) lv_group_add_obj(g, btnm); - lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); - lv_obj_set_scroll_snap_x(cont, LV_SCROLL_SNAP_CENTER); + if((tabview->tab_pos & LV_DIR_VER) != 0) { + lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); + lv_obj_set_scroll_snap_x(cont, LV_SCROLL_SNAP_CENTER); + } + else { + lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); + lv_obj_set_scroll_snap_y(cont, LV_SCROLL_SNAP_CENTER); + } lv_obj_add_flag(cont, LV_OBJ_FLAG_SCROLL_ONE); lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLL_ON_FOCUS); } @@ -289,18 +317,29 @@ static void cont_scroll_end_event_cb(lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); lv_obj_t * tv = lv_obj_get_parent(cont); + lv_tabview_t * tv_obj = (lv_tabview_t *)tv; if(code == LV_EVENT_LAYOUT_CHANGED) { lv_tabview_set_act(tv, lv_tabview_get_tab_act(tv), LV_ANIM_OFF); } else if(code == LV_EVENT_SCROLL_END) { + lv_indev_t * indev = lv_indev_get_act(); + if(indev && indev->proc.state == LV_INDEV_STATE_PRESSED) { + return; + } + lv_point_t p; lv_obj_get_scroll_end(cont, &p); - lv_coord_t w = lv_obj_get_content_width(cont); lv_coord_t t; - - if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w / 2) / w; - else t = (p.x + w / 2) / w; + if((tv_obj->tab_pos & LV_DIR_VER) != 0) { + lv_coord_t w = lv_obj_get_content_width(cont); + if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w / 2) / w; + else t = (p.x + w / 2) / w; + } + else { + lv_coord_t h = lv_obj_get_content_height(cont); + t = (p.y + h / 2) / h; + } if(t < 0) t = 0; bool new_tab = false; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h index a01c6b9ba..388c65477 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h @@ -42,6 +42,8 @@ lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab lv_obj_t * lv_tabview_add_tab(lv_obj_t * tv, const char * name); +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t tab_id, const char * new_name); + lv_obj_t * lv_tabview_get_content(lv_obj_t * tv); lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c index 4f98b552a..17fdb519a 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c +++ b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c @@ -7,6 +7,7 @@ * INCLUDES *********************/ #include "lv_tileview.h" +#include "../../../core/lv_indev.h" #if LV_USE_TILEVIEW /********************* @@ -157,6 +158,11 @@ static void tileview_event_cb(lv_event_t * e) lv_tileview_t * tv = (lv_tileview_t *) obj; if(code == LV_EVENT_SCROLL_END) { + lv_indev_t * indev = lv_indev_get_act(); + if(indev && indev->proc.state == LV_INDEV_STATE_PRESSED) { + return; + } + lv_coord_t w = lv_obj_get_content_width(obj); lv_coord_t h = lv_obj_get_content_height(obj); diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c index 0e7a2fe74..d4cc27e19 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c @@ -43,7 +43,7 @@ /** * Return with the bitmap of a font. * @param font_p pointer to a font - * @param letter an UNICODE character code + * @param letter a UNICODE character code * @return pointer to the bitmap of the letter */ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter) @@ -56,7 +56,7 @@ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t lett * Get the descriptor of a glyph * @param font_p pointer to font * @param dsc_out store the result descriptor here - * @param letter an UNICODE letter code + * @param letter a UNICODE letter code * @param letter_next the next letter after `letter`. Used for kerning * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` @@ -64,26 +64,72 @@ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t lett bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) { + LV_ASSERT_NULL(font_p); LV_ASSERT_NULL(dsc_out); - dsc_out->resolved_font = NULL; + +#if LV_USE_FONT_PLACEHOLDER + const lv_font_t * placeholder_font = NULL; +#endif + const lv_font_t * f = font_p; - bool found = false; + + dsc_out->resolved_font = NULL; + while(f) { - found = f->get_glyph_dsc(f, dsc_out, letter, letter_next); - if(found && !dsc_out->is_placeholder) { - dsc_out->resolved_font = f; - break; + bool found = f->get_glyph_dsc(f, dsc_out, letter, letter_next); + if(found) { + if(!dsc_out->is_placeholder) { + dsc_out->resolved_font = f; + return true; + } +#if LV_USE_FONT_PLACEHOLDER + else if(placeholder_font == NULL) { + placeholder_font = f; + } +#endif } f = f->fallback; } - return found; + +#if LV_USE_FONT_PLACEHOLDER + if(placeholder_font != NULL) { + placeholder_font->get_glyph_dsc(placeholder_font, dsc_out, letter, letter_next); + dsc_out->resolved_font = placeholder_font; + return true; + } +#endif + + if(letter < 0x20 || + letter == 0xf8ff || /*LV_SYMBOL_DUMMY*/ + letter == 0x200c) { /*ZERO WIDTH NON-JOINER*/ + dsc_out->box_w = 0; + dsc_out->adv_w = 0; + } + else { +#if LV_USE_FONT_PLACEHOLDER + dsc_out->box_w = font_p->line_height / 2; + dsc_out->adv_w = dsc_out->box_w + 2; +#else + dsc_out->box_w = 0; + dsc_out->adv_w = 0; +#endif + } + + dsc_out->resolved_font = NULL; + dsc_out->box_h = font_p->line_height; + dsc_out->ofs_x = 0; + dsc_out->ofs_y = 0; + dsc_out->bpp = 1; + dsc_out->is_placeholder = true; + + return false; } /** * Get the width of a glyph with kerning * @param font pointer to a font - * @param letter an UNICODE letter + * @param letter a UNICODE letter * @param letter_next the next letter after `letter`. Used for kerning * @return the width of the glyph */ @@ -91,10 +137,8 @@ uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32 { LV_ASSERT_NULL(font); lv_font_glyph_dsc_t g; - bool ret; - ret = lv_font_get_glyph_dsc(font, &g, letter, letter_next); - if(ret) return g.adv_w; - else return 0; + lv_font_get_glyph_dsc(font, &g, letter, letter_next); + return g.adv_w; } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font.h index 3d716dd46..e3b670c87 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font.h @@ -25,6 +25,9 @@ extern "C" { * DEFINES *********************/ +/* imgfont identifier */ +#define LV_IMGFONT_BPP 9 + /********************** * TYPEDEFS **********************/ @@ -37,7 +40,7 @@ struct _lv_font_t; /** Describes the properties of a glyph.*/ typedef struct { const struct _lv_font_t * - resolved_font; /**< Pointer to a font where the gylph was actually found after handling fallbacks*/ + resolved_font; /**< Pointer to a font where the glyph was actually found after handling fallbacks*/ uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width.*/ uint16_t box_w; /**< Width of the glyph's bounding box*/ uint16_t box_h; /**< Height of the glyph's bounding box*/ @@ -87,7 +90,7 @@ typedef struct _lv_font_t { /** * Return with the bitmap of a font. * @param font_p pointer to a font - * @param letter an UNICODE character code + * @param letter a UNICODE character code * @return pointer to the bitmap of the letter */ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter); @@ -96,7 +99,7 @@ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t lett * Get the descriptor of a glyph * @param font_p pointer to font * @param dsc_out store the result descriptor here - * @param letter an UNICODE letter code + * @param letter a UNICODE letter code * @param letter_next the next letter after `letter`. Used for kerning * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` @@ -107,7 +110,7 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o /** * Get the width of a glyph with kerning * @param font pointer to a font - * @param letter an UNICODE letter + * @param letter a UNICODE letter * @param letter_next the next letter after `letter`. Used for kerning * @return the width of the glyph */ @@ -243,7 +246,7 @@ LV_FONT_CUSTOM_DECLARE #endif /** - * Just a wrapper around LV_FONT_DEFAULT because it might be more convenient to use a function is some cases + * Just a wrapper around LV_FONT_DEFAULT because it might be more convenient to use a function in some cases * @return pointer to LV_FONT_DEFAULT */ static inline const lv_font_t * lv_font_default(void) diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c index 452cbe912..7a36f01b8 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c @@ -73,7 +73,7 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element); /** * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. * @param font pointer to font - * @param unicode_letter an unicode letter which bitmap should be get + * @param unicode_letter a unicode letter which bitmap should be get * @return pointer to the bitmap or NULL if not found */ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unicode_letter) @@ -141,7 +141,7 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. * @param font_p pointer to font * @param dsc_out store the result descriptor here - * @param letter an UNICODE letter code + * @param letter a UNICODE letter code * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` */ diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h index 9c9d422a8..86546a35f 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h @@ -170,7 +170,7 @@ typedef struct { /** * Store kerning values. - * Can be `lv_font_fmt_txt_kern_pair_t * or `lv_font_kern_classes_fmt_txt_t *` + * Can be `lv_font_fmt_txt_kern_pair_t * or `lv_font_kern_classes_fmt_txt_t *` * depending on `kern_classes` */ const void * kern_dsc; @@ -204,7 +204,7 @@ typedef struct { /** * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. * @param font pointer to font - * @param unicode_letter an unicode letter which bitmap should be get + * @param unicode_letter a unicode letter which bitmap should be get * @return pointer to the bitmap or NULL if not found */ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t letter); @@ -213,7 +213,7 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t lett * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. * @param font_p pointer to font * @param dsc_out store the result descriptor here - * @param letter an UNICODE letter code + * @param letter a UNICODE letter code * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` */ diff --git a/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk b/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk deleted file mode 100644 index f810e0c70..000000000 --- a/lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk +++ /dev/null @@ -1,10 +0,0 @@ -CSRCS += lv_gpu_nxp_pxp.c -CSRCS += lv_gpu_nxp_pxp_osa.c -CSRCS += lv_gpu_nxp_vglite.c -CSRCS += lv_gpu_stm32_dma2d.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/gpu" - diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c index 9a8e42d28..0dd8f6b30 100644 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c +++ b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c @@ -21,6 +21,11 @@ #include "../draw/sw/lv_draw_sw.h" #include "../draw/sdl/lv_draw_sdl.h" #include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h" +#include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h" +#include "../draw/arm2d/lv_gpu_arm2d.h" +#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE + #include "../draw/nxp/lv_gpu_nxp.h" +#endif #if LV_USE_THEME_DEFAULT #include "../extra/themes/default/lv_theme_default.h" @@ -87,7 +92,7 @@ void lv_disp_drv_init(lv_disp_drv_t * driver) driver->offset_x = 0; driver->offset_y = 0; driver->antialiasing = LV_COLOR_DEPTH > 8 ? 1 : 0; - driver->screen_transp = LV_COLOR_SCREEN_TRANSP; + driver->screen_transp = 0; driver->dpi = LV_DPI_DEF; driver->color_chroma_key = LV_COLOR_CHROMA_KEY; @@ -96,18 +101,22 @@ void lv_disp_drv_init(lv_disp_drv_t * driver) driver->draw_ctx_init = lv_draw_stm32_dma2d_ctx_init; driver->draw_ctx_deinit = lv_draw_stm32_dma2d_ctx_init; driver->draw_ctx_size = sizeof(lv_draw_stm32_dma2d_ctx_t); -#elif LV_USE_GPU_NXP_PXP - driver->draw_ctx_init = lv_draw_nxp_pxp_init; - driver->draw_ctx_deinit = lv_draw_nxp_pxp_init; - driver->draw_ctx_size = sizeof(lv_draw_nxp_pxp_t); -#elif LV_USE_GPU_NXP_VG_LITE - driver->draw_ctx_init = lv_draw_nxp_vglite_init; - driver->draw_ctx_deinit = lv_draw_nxp_vglite_init; - driver->draw_ctx_size = sizeof(lv_draw_nxp_vglite_t); +#elif LV_USE_GPU_SWM341_DMA2D + driver->draw_ctx_init = lv_draw_swm341_dma2d_ctx_init; + driver->draw_ctx_deinit = lv_draw_swm341_dma2d_ctx_init; + driver->draw_ctx_size = sizeof(lv_draw_swm341_dma2d_ctx_t); +#elif LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE + driver->draw_ctx_init = lv_draw_nxp_ctx_init; + driver->draw_ctx_deinit = lv_draw_nxp_ctx_deinit; + driver->draw_ctx_size = sizeof(lv_draw_nxp_ctx_t); #elif LV_USE_GPU_SDL driver->draw_ctx_init = lv_draw_sdl_init_ctx; driver->draw_ctx_deinit = lv_draw_sdl_deinit_ctx; driver->draw_ctx_size = sizeof(lv_draw_sdl_ctx_t); +#elif LV_USE_GPU_ARM2D + driver->draw_ctx_init = lv_draw_arm2d_ctx_init; + driver->draw_ctx_deinit = lv_draw_arm2d_ctx_init; + driver->draw_ctx_size = sizeof(lv_draw_arm2d_ctx_t); #else driver->draw_ctx_init = lv_draw_sw_init_ctx; driver->draw_ctx_deinit = lv_draw_sw_init_ctx; @@ -150,8 +159,8 @@ void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * bu lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) { lv_disp_t * disp = _lv_ll_ins_head(&LV_GC_ROOT(_lv_disp_ll)); + LV_ASSERT_MALLOC(disp); if(!disp) { - LV_ASSERT_MALLOC(disp); return NULL; } @@ -168,6 +177,8 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) disp->driver = driver; + disp->inv_en_cnt = 1; + lv_disp_t * disp_def_tmp = disp_def; disp_def = disp; /*Temporarily change the default screen to create the default screens on the new display*/ @@ -497,18 +508,6 @@ lv_coord_t lv_disp_get_dpi(const lv_disp_t * disp) */ LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv) { - /*If the screen is transparent initialize it when the flushing is ready*/ -#if LV_COLOR_SCREEN_TRANSP - if(disp_drv->screen_transp) { - if(disp_drv->clear_cb) { - disp_drv->clear_cb(disp_drv, disp_drv->draw_buf->buf_act, disp_drv->draw_buf->size); - } - else { - lv_memset_00(disp_drv->draw_buf->buf_act, disp_drv->draw_buf->size * sizeof(lv_color32_t)); - } - } -#endif - disp_drv->draw_buf->flushing = 0; disp_drv->draw_buf->flushing_last = 0; } @@ -677,28 +676,35 @@ static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, l lv_img_buf_set_px_alpha(d, x, y, br); } -static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, +static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, + lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) { (void) disp_drv; /*Unused*/ - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.always_zero = 0; - d.header.h = 1; /*Doesn't matter*/; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + uint8_t * buf_px = buf + (buf_w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE); - lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, lv_color_black()); - lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y); - - lv_opa_t res_opa; + lv_color_t bg_color; lv_color_t res_color; + lv_opa_t bg_opa = buf_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + bg_color.full = buf_px[0]; + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[2]); + if(buf_px[1] <= LV_OPA_MIN) return; + buf_px[0] = res_color.full; +#elif LV_COLOR_DEPTH == 16 + bg_color.full = buf_px[0] + (buf_px[1] << 8); + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[2]); + if(buf_px[2] <= LV_OPA_MIN) return; + buf_px[0] = res_color.full & 0xff; + buf_px[1] = res_color.full >> 8; +#elif LV_COLOR_DEPTH == 32 + bg_color = *((lv_color_t *)buf_px); + lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[3]); + if(buf_px[3] <= LV_OPA_MIN) return; + buf_px[0] = res_color.ch.blue; + buf_px[1] = res_color.ch.green; + buf_px[2] = res_color.ch.red; +#endif - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa); - - lv_img_buf_set_px_alpha(&d, x, y, res_opa); - lv_img_buf_set_px_color(&d, x, y, res_color); } diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h index 6abbab1f9..d3425fe4e 100644 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h +++ b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h @@ -133,6 +133,9 @@ typedef struct _lv_disp_drv_t { /** OPTIONAL: called when driver parameters are updated */ void (*drv_update_cb)(struct _lv_disp_drv_t * disp_drv); + /** OPTIONAL: called when start rendering */ + void (*render_start_cb)(struct _lv_disp_drv_t * disp_drv); + /** On CHROMA_KEYED images this color will be transparent. * `LV_COLOR_CHROMA_KEY` by default. (lv_conf.h)*/ lv_color_t color_chroma_key; @@ -170,8 +173,11 @@ typedef struct _lv_disp_t { struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top*/ struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys*/ uint32_t screen_cnt; +uint8_t draw_prev_over_act : + 1; /**< 1: Draw previous screen over active screen*/ uint8_t del_prev : 1; /**< 1: Automatically delete the previous screen when the screen load animation is ready*/ + uint8_t rendering_in_progress : 1; /**< 1: The current screen rendering is in progress*/ lv_opa_t bg_opa; /**disp == NULL) driver->disp = lv_disp_get_default(); if(driver->disp == NULL) { @@ -85,8 +84,8 @@ lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver) } lv_indev_t * indev = _lv_ll_ins_head(&LV_GC_ROOT(_lv_indev_ll)); + LV_ASSERT_MALLOC(indev); if(!indev) { - LV_ASSERT_MALLOC(indev); return NULL; } diff --git a/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h b/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h index b3e6748bb..97807fe37 100644 --- a/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h +++ b/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h @@ -12,38 +12,43 @@ /* Handle special Kconfig options */ #ifndef LV_KCONFIG_IGNORE -# include "lv_conf_kconfig.h" -# ifdef CONFIG_LV_CONF_SKIP -# define LV_CONF_SKIP -# endif + #include "lv_conf_kconfig.h" + #ifdef CONFIG_LV_CONF_SKIP + #define LV_CONF_SKIP + #endif #endif /*If "lv_conf.h" is available from here try to use it later.*/ #ifdef __has_include -# if __has_include("lv_conf.h") -# ifndef LV_CONF_INCLUDE_SIMPLE -# define LV_CONF_INCLUDE_SIMPLE -# endif -# endif + #if __has_include("lv_conf.h") + #ifndef LV_CONF_INCLUDE_SIMPLE + #define LV_CONF_INCLUDE_SIMPLE + #endif + #endif #endif /*If lv_conf.h is not skipped include it*/ #ifndef LV_CONF_SKIP -# ifdef LV_CONF_PATH /*If there is a path defined for lv_conf.h use it*/ -# define __LV_TO_STR_AUX(x) #x -# define __LV_TO_STR(x) __LV_TO_STR_AUX(x) -# include __LV_TO_STR(LV_CONF_PATH) -# undef __LV_TO_STR_AUX -# undef __LV_TO_STR -# elif defined(LV_CONF_INCLUDE_SIMPLE) /*Or simply include lv_conf.h is enabled*/ -# include "lv_conf.h" -# else -# include "../../lv_conf.h" /*Else assume lv_conf.h is next to the lvgl folder*/ -# endif + #ifdef LV_CONF_PATH /*If there is a path defined for lv_conf.h use it*/ + #define __LV_TO_STR_AUX(x) #x + #define __LV_TO_STR(x) __LV_TO_STR_AUX(x) + #include __LV_TO_STR(LV_CONF_PATH) + #undef __LV_TO_STR_AUX + #undef __LV_TO_STR + #elif defined(LV_CONF_INCLUDE_SIMPLE) /*Or simply include lv_conf.h is enabled*/ + #include "lv_conf.h" + #else + #include "../../lv_conf.h" /*Else assume lv_conf.h is next to the lvgl folder*/ + #endif + #if !defined(LV_CONF_H) && !defined(LV_CONF_SUPPRESS_DEFINE_CHECK) + /* #include will sometimes silently fail when __has_include is used */ + /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80753 */ + #pragma message("Possible failure to include lv_conf.h, please read the comment in this file if you get errors") + #endif #endif #ifdef CONFIG_LV_COLOR_DEPTH -# define _LV_KCONFIG_PRESENT + #define _LV_KCONFIG_PRESENT #endif /*---------------------------------- @@ -58,50 +63,50 @@ /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ #ifndef LV_COLOR_DEPTH -# ifdef CONFIG_LV_COLOR_DEPTH -# define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH -# else -# define LV_COLOR_DEPTH 16 -# endif + #ifdef CONFIG_LV_COLOR_DEPTH + #define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH + #else + #define LV_COLOR_DEPTH 16 + #endif #endif /*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ #ifndef LV_COLOR_16_SWAP -# ifdef CONFIG_LV_COLOR_16_SWAP -# define LV_COLOR_16_SWAP CONFIG_LV_COLOR_16_SWAP -# else -# define LV_COLOR_16_SWAP 0 -# endif + #ifdef CONFIG_LV_COLOR_16_SWAP + #define LV_COLOR_16_SWAP CONFIG_LV_COLOR_16_SWAP + #else + #define LV_COLOR_16_SWAP 0 + #endif #endif -/*Enable more complex drawing routines to manage screens transparency. - *Can be used if the UI is above another layer, e.g. an OSD menu or video player. - *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ +/*Enable features to draw on transparent background. + *It's required if opa, and transform_* style properties are used. + *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ #ifndef LV_COLOR_SCREEN_TRANSP -# ifdef CONFIG_LV_COLOR_SCREEN_TRANSP -# define LV_COLOR_SCREEN_TRANSP CONFIG_LV_COLOR_SCREEN_TRANSP -# else -# define LV_COLOR_SCREEN_TRANSP 0 -# endif + #ifdef CONFIG_LV_COLOR_SCREEN_TRANSP + #define LV_COLOR_SCREEN_TRANSP CONFIG_LV_COLOR_SCREEN_TRANSP + #else + #define LV_COLOR_SCREEN_TRANSP 0 + #endif #endif /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ #ifndef LV_COLOR_MIX_ROUND_OFS -# ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS -# define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS -# else -# define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) -# endif + #ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS + #define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS + #else + #define LV_COLOR_MIX_ROUND_OFS 0 + #endif #endif /*Images pixels with this color will not be drawn if they are chroma keyed)*/ #ifndef LV_COLOR_CHROMA_KEY -# ifdef CONFIG_LV_COLOR_CHROMA_KEY -# define LV_COLOR_CHROMA_KEY CONFIG_LV_COLOR_CHROMA_KEY -# else -# define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ -# endif + #ifdef CONFIG_LV_COLOR_CHROMA_KEY + #define LV_COLOR_CHROMA_KEY CONFIG_LV_COLOR_CHROMA_KEY + #else + #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ + #endif #endif /*========================= @@ -110,84 +115,96 @@ /*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ #ifndef LV_MEM_CUSTOM -# ifdef CONFIG_LV_MEM_CUSTOM -# define LV_MEM_CUSTOM CONFIG_LV_MEM_CUSTOM -# else -# define LV_MEM_CUSTOM 0 -# endif + #ifdef CONFIG_LV_MEM_CUSTOM + #define LV_MEM_CUSTOM CONFIG_LV_MEM_CUSTOM + #else + #define LV_MEM_CUSTOM 0 + #endif #endif #if LV_MEM_CUSTOM == 0 -/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ -#ifndef LV_MEM_SIZE -# ifdef CONFIG_LV_MEM_SIZE -# define LV_MEM_SIZE CONFIG_LV_MEM_SIZE -# else -# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/ -# endif -#endif + /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ + #ifndef LV_MEM_SIZE + #ifdef CONFIG_LV_MEM_SIZE + #define LV_MEM_SIZE CONFIG_LV_MEM_SIZE + #else + #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ + #endif + #endif -/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ -#ifndef LV_MEM_ADR -# ifdef CONFIG_LV_MEM_ADR -# define LV_MEM_ADR CONFIG_LV_MEM_ADR -# else -# define LV_MEM_ADR 0 /*0: unused*/ -# endif -#endif -/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ -#if LV_MEM_ADR == 0 -//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ -//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ -#endif + /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ + #ifndef LV_MEM_ADR + #ifdef CONFIG_LV_MEM_ADR + #define LV_MEM_ADR CONFIG_LV_MEM_ADR + #else + #define LV_MEM_ADR 0 /*0: unused*/ + #endif + #endif + /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ + #if LV_MEM_ADR == 0 + #ifndef LV_MEM_POOL_INCLUDE + #ifdef CONFIG_LV_MEM_POOL_INCLUDE + #define LV_MEM_POOL_INCLUDE CONFIG_LV_MEM_POOL_INCLUDE + #else + #undef LV_MEM_POOL_INCLUDE + #endif + #endif + #ifndef LV_MEM_POOL_ALLOC + #ifdef CONFIG_LV_MEM_POOL_ALLOC + #define LV_MEM_POOL_ALLOC CONFIG_LV_MEM_POOL_ALLOC + #else + #undef LV_MEM_POOL_ALLOC + #endif + #endif + #endif #else /*LV_MEM_CUSTOM*/ -#ifndef LV_MEM_CUSTOM_INCLUDE -# ifdef CONFIG_LV_MEM_CUSTOM_INCLUDE -# define LV_MEM_CUSTOM_INCLUDE CONFIG_LV_MEM_CUSTOM_INCLUDE -# else -# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -# endif -#endif -#ifndef LV_MEM_CUSTOM_ALLOC -# ifdef CONFIG_LV_MEM_CUSTOM_ALLOC -# define LV_MEM_CUSTOM_ALLOC CONFIG_LV_MEM_CUSTOM_ALLOC -# else -# define LV_MEM_CUSTOM_ALLOC malloc -# endif -#endif -#ifndef LV_MEM_CUSTOM_FREE -# ifdef CONFIG_LV_MEM_CUSTOM_FREE -# define LV_MEM_CUSTOM_FREE CONFIG_LV_MEM_CUSTOM_FREE -# else -# define LV_MEM_CUSTOM_FREE free -# endif -#endif -#ifndef LV_MEM_CUSTOM_REALLOC -# ifdef CONFIG_LV_MEM_CUSTOM_REALLOC -# define LV_MEM_CUSTOM_REALLOC CONFIG_LV_MEM_CUSTOM_REALLOC -# else -# define LV_MEM_CUSTOM_REALLOC realloc -# endif -#endif + #ifndef LV_MEM_CUSTOM_INCLUDE + #ifdef CONFIG_LV_MEM_CUSTOM_INCLUDE + #define LV_MEM_CUSTOM_INCLUDE CONFIG_LV_MEM_CUSTOM_INCLUDE + #else + #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ + #endif + #endif + #ifndef LV_MEM_CUSTOM_ALLOC + #ifdef CONFIG_LV_MEM_CUSTOM_ALLOC + #define LV_MEM_CUSTOM_ALLOC CONFIG_LV_MEM_CUSTOM_ALLOC + #else + #define LV_MEM_CUSTOM_ALLOC malloc + #endif + #endif + #ifndef LV_MEM_CUSTOM_FREE + #ifdef CONFIG_LV_MEM_CUSTOM_FREE + #define LV_MEM_CUSTOM_FREE CONFIG_LV_MEM_CUSTOM_FREE + #else + #define LV_MEM_CUSTOM_FREE free + #endif + #endif + #ifndef LV_MEM_CUSTOM_REALLOC + #ifdef CONFIG_LV_MEM_CUSTOM_REALLOC + #define LV_MEM_CUSTOM_REALLOC CONFIG_LV_MEM_CUSTOM_REALLOC + #else + #define LV_MEM_CUSTOM_REALLOC realloc + #endif + #endif #endif /*LV_MEM_CUSTOM*/ /*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. *You will see an error log message if there wasn't enough buffers. */ #ifndef LV_MEM_BUF_MAX_NUM -# ifdef CONFIG_LV_MEM_BUF_MAX_NUM -# define LV_MEM_BUF_MAX_NUM CONFIG_LV_MEM_BUF_MAX_NUM -# else -# define LV_MEM_BUF_MAX_NUM 16 -# endif + #ifdef CONFIG_LV_MEM_BUF_MAX_NUM + #define LV_MEM_BUF_MAX_NUM CONFIG_LV_MEM_BUF_MAX_NUM + #else + #define LV_MEM_BUF_MAX_NUM 16 + #endif #endif /*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ #ifndef LV_MEMCPY_MEMSET_STD -# ifdef CONFIG_LV_MEMCPY_MEMSET_STD -# define LV_MEMCPY_MEMSET_STD CONFIG_LV_MEMCPY_MEMSET_STD -# else -# define LV_MEMCPY_MEMSET_STD 0 -# endif + #ifdef CONFIG_LV_MEMCPY_MEMSET_STD + #define LV_MEMCPY_MEMSET_STD CONFIG_LV_MEMCPY_MEMSET_STD + #else + #define LV_MEMCPY_MEMSET_STD 0 + #endif #endif /*==================== @@ -196,56 +213,56 @@ /*Default display refresh period. LVG will redraw changed areas with this period time*/ #ifndef LV_DISP_DEF_REFR_PERIOD -# ifdef CONFIG_LV_DISP_DEF_REFR_PERIOD -# define LV_DISP_DEF_REFR_PERIOD CONFIG_LV_DISP_DEF_REFR_PERIOD -# else -# define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ -# endif + #ifdef CONFIG_LV_DISP_DEF_REFR_PERIOD + #define LV_DISP_DEF_REFR_PERIOD CONFIG_LV_DISP_DEF_REFR_PERIOD + #else + #define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ + #endif #endif /*Input device read period in milliseconds*/ #ifndef LV_INDEV_DEF_READ_PERIOD -# ifdef CONFIG_LV_INDEV_DEF_READ_PERIOD -# define LV_INDEV_DEF_READ_PERIOD CONFIG_LV_INDEV_DEF_READ_PERIOD -# else -# define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ -# endif + #ifdef CONFIG_LV_INDEV_DEF_READ_PERIOD + #define LV_INDEV_DEF_READ_PERIOD CONFIG_LV_INDEV_DEF_READ_PERIOD + #else + #define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ + #endif #endif /*Use a custom tick source that tells the elapsed time in milliseconds. *It removes the need to manually update the tick with `lv_tick_inc()`)*/ #ifndef LV_TICK_CUSTOM -# ifdef CONFIG_LV_TICK_CUSTOM -# define LV_TICK_CUSTOM CONFIG_LV_TICK_CUSTOM -# else -# define LV_TICK_CUSTOM 0 -# endif + #ifdef CONFIG_LV_TICK_CUSTOM + #define LV_TICK_CUSTOM CONFIG_LV_TICK_CUSTOM + #else + #define LV_TICK_CUSTOM 0 + #endif #endif #if LV_TICK_CUSTOM -#ifndef LV_TICK_CUSTOM_INCLUDE -# ifdef CONFIG_LV_TICK_CUSTOM_INCLUDE -# define LV_TICK_CUSTOM_INCLUDE CONFIG_LV_TICK_CUSTOM_INCLUDE -# else -# define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ -# endif -#endif -#ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR -# ifdef CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR -# define LV_TICK_CUSTOM_SYS_TIME_EXPR CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR -# else -# define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ -# endif -#endif + #ifndef LV_TICK_CUSTOM_INCLUDE + #ifdef CONFIG_LV_TICK_CUSTOM_INCLUDE + #define LV_TICK_CUSTOM_INCLUDE CONFIG_LV_TICK_CUSTOM_INCLUDE + #else + #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ + #endif + #endif + #ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR + #ifdef CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR + #define LV_TICK_CUSTOM_SYS_TIME_EXPR CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR + #else + #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ + #endif + #endif #endif /*LV_TICK_CUSTOM*/ /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ #ifndef LV_DPI_DEF -# ifdef CONFIG_LV_DPI_DEF -# define LV_DPI_DEF CONFIG_LV_DPI_DEF -# else -# define LV_DPI_DEF 130 /*[px/inch]*/ -# endif + #ifdef CONFIG_LV_DPI_DEF + #define LV_DPI_DEF CONFIG_LV_DPI_DEF + #else + #define LV_DPI_DEF 130 /*[px/inch]*/ + #endif #endif /*======================= @@ -259,146 +276,254 @@ /*Enable complex draw engine. *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ #ifndef LV_DRAW_COMPLEX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_DRAW_COMPLEX -# define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX -# else -# define LV_DRAW_COMPLEX 0 -# endif -# else -# define LV_DRAW_COMPLEX 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_DRAW_COMPLEX + #define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX + #else + #define LV_DRAW_COMPLEX 0 + #endif + #else + #define LV_DRAW_COMPLEX 1 + #endif #endif #if LV_DRAW_COMPLEX != 0 -/*Allow buffering some shadow calculation. - *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` - *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ -#ifndef LV_SHADOW_CACHE_SIZE -# ifdef CONFIG_LV_SHADOW_CACHE_SIZE -# define LV_SHADOW_CACHE_SIZE CONFIG_LV_SHADOW_CACHE_SIZE -# else -# define LV_SHADOW_CACHE_SIZE 0 -# endif -#endif - -/* Set number of maximally cached circle data. - * The circumference of 1/4 circle are saved for anti-aliasing - * radius * 4 bytes are used per circle (the most often used radiuses are saved) - * 0: to disable caching */ -#ifndef LV_CIRCLE_CACHE_SIZE -# ifdef CONFIG_LV_CIRCLE_CACHE_SIZE -# define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE -# else -# define LV_CIRCLE_CACHE_SIZE 4 -# endif -#endif + /*Allow buffering some shadow calculation. + *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ + #ifndef LV_SHADOW_CACHE_SIZE + #ifdef CONFIG_LV_SHADOW_CACHE_SIZE + #define LV_SHADOW_CACHE_SIZE CONFIG_LV_SHADOW_CACHE_SIZE + #else + #define LV_SHADOW_CACHE_SIZE 0 + #endif + #endif + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #ifndef LV_CIRCLE_CACHE_SIZE + #ifdef CONFIG_LV_CIRCLE_CACHE_SIZE + #define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE + #else + #define LV_CIRCLE_CACHE_SIZE 4 + #endif + #endif #endif /*LV_DRAW_COMPLEX*/ +/** + * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer + * and blend it as an image with the given opacity. + * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) + * The widget can be buffered in smaller chunks to avoid using large buffers. + * + * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it + * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. + * + * Both buffer sizes are in bytes. + * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers + * and can't be drawn in chunks. So these settings affects only widgets with opacity. + */ +#ifndef LV_LAYER_SIMPLE_BUF_SIZE + #ifdef CONFIG_LV_LAYER_SIMPLE_BUF_SIZE + #define LV_LAYER_SIMPLE_BUF_SIZE CONFIG_LV_LAYER_SIMPLE_BUF_SIZE + #else + #define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) + #endif +#endif +#ifndef LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE + #ifdef CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE + #define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE + #else + #define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) + #endif +#endif + /*Default image cache size. Image caching keeps the images opened. *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. *However the opened images might consume additional RAM. *0: to disable caching*/ #ifndef LV_IMG_CACHE_DEF_SIZE -# ifdef CONFIG_LV_IMG_CACHE_DEF_SIZE -# define LV_IMG_CACHE_DEF_SIZE CONFIG_LV_IMG_CACHE_DEF_SIZE -# else -# define LV_IMG_CACHE_DEF_SIZE 0 -# endif + #ifdef CONFIG_LV_IMG_CACHE_DEF_SIZE + #define LV_IMG_CACHE_DEF_SIZE CONFIG_LV_IMG_CACHE_DEF_SIZE + #else + #define LV_IMG_CACHE_DEF_SIZE 0 + #endif #endif -/*Maximum buffer size to allocate for rotation. Only used if software rotation is enabled in the display driver.*/ +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#ifndef LV_GRADIENT_MAX_STOPS + #ifdef CONFIG_LV_GRADIENT_MAX_STOPS + #define LV_GRADIENT_MAX_STOPS CONFIG_LV_GRADIENT_MAX_STOPS + #else + #define LV_GRADIENT_MAX_STOPS 2 + #endif +#endif + +/*Default gradient buffer size. + *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. + *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. + *If the cache is too small the map will be allocated only while it's required for the drawing. + *0 mean no caching.*/ +#ifndef LV_GRAD_CACHE_DEF_SIZE + #ifdef CONFIG_LV_GRAD_CACHE_DEF_SIZE + #define LV_GRAD_CACHE_DEF_SIZE CONFIG_LV_GRAD_CACHE_DEF_SIZE + #else + #define LV_GRAD_CACHE_DEF_SIZE 0 + #endif +#endif + +/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) + *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface + *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ +#ifndef LV_DITHER_GRADIENT + #ifdef CONFIG_LV_DITHER_GRADIENT + #define LV_DITHER_GRADIENT CONFIG_LV_DITHER_GRADIENT + #else + #define LV_DITHER_GRADIENT 0 + #endif +#endif +#if LV_DITHER_GRADIENT + /*Add support for error diffusion dithering. + *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. + *The increase in memory consumption is (24 bits * object's width)*/ + #ifndef LV_DITHER_ERROR_DIFFUSION + #ifdef CONFIG_LV_DITHER_ERROR_DIFFUSION + #define LV_DITHER_ERROR_DIFFUSION CONFIG_LV_DITHER_ERROR_DIFFUSION + #else + #define LV_DITHER_ERROR_DIFFUSION 0 + #endif + #endif +#endif + +/*Maximum buffer size to allocate for rotation. + *Only used if software rotation is enabled in the display driver.*/ #ifndef LV_DISP_ROT_MAX_BUF -# ifdef CONFIG_LV_DISP_ROT_MAX_BUF -# define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF -# else -# define LV_DISP_ROT_MAX_BUF (10*1024) -# endif + #ifdef CONFIG_LV_DISP_ROT_MAX_BUF + #define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF + #else + #define LV_DISP_ROT_MAX_BUF (10*1024) + #endif #endif /*------------- * GPU *-----------*/ +/*Use Arm's 2D acceleration library Arm-2D */ +#ifndef LV_USE_GPU_ARM2D + #ifdef CONFIG_LV_USE_GPU_ARM2D + #define LV_USE_GPU_ARM2D CONFIG_LV_USE_GPU_ARM2D + #else + #define LV_USE_GPU_ARM2D 0 + #endif +#endif + /*Use STM32's DMA2D (aka Chrom Art) GPU*/ #ifndef LV_USE_GPU_STM32_DMA2D -# ifdef CONFIG_LV_USE_GPU_STM32_DMA2D -# define LV_USE_GPU_STM32_DMA2D CONFIG_LV_USE_GPU_STM32_DMA2D -# else -# define LV_USE_GPU_STM32_DMA2D 0 -# endif + #ifdef CONFIG_LV_USE_GPU_STM32_DMA2D + #define LV_USE_GPU_STM32_DMA2D CONFIG_LV_USE_GPU_STM32_DMA2D + #else + #define LV_USE_GPU_STM32_DMA2D 0 + #endif #endif #if LV_USE_GPU_STM32_DMA2D -/*Must be defined to include path of CMSIS header of target processor -e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ -#ifndef LV_GPU_DMA2D_CMSIS_INCLUDE -# ifdef CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE -# define LV_GPU_DMA2D_CMSIS_INCLUDE CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE -# else -# define LV_GPU_DMA2D_CMSIS_INCLUDE -# endif + /*Must be defined to include path of CMSIS header of target processor + e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ + #ifndef LV_GPU_DMA2D_CMSIS_INCLUDE + #ifdef CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE + #define LV_GPU_DMA2D_CMSIS_INCLUDE CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE + #else + #define LV_GPU_DMA2D_CMSIS_INCLUDE + #endif + #endif #endif + +/*Use SWM341's DMA2D GPU*/ +#ifndef LV_USE_GPU_SWM341_DMA2D + #ifdef CONFIG_LV_USE_GPU_SWM341_DMA2D + #define LV_USE_GPU_SWM341_DMA2D CONFIG_LV_USE_GPU_SWM341_DMA2D + #else + #define LV_USE_GPU_SWM341_DMA2D 0 + #endif +#endif +#if LV_USE_GPU_SWM341_DMA2D + #ifndef LV_GPU_SWM341_DMA2D_INCLUDE + #ifdef CONFIG_LV_GPU_SWM341_DMA2D_INCLUDE + #define LV_GPU_SWM341_DMA2D_INCLUDE CONFIG_LV_GPU_SWM341_DMA2D_INCLUDE + #else + #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" + #endif + #endif #endif /*Use NXP's PXP GPU iMX RTxxx platforms*/ #ifndef LV_USE_GPU_NXP_PXP -# ifdef CONFIG_LV_USE_GPU_NXP_PXP -# define LV_USE_GPU_NXP_PXP CONFIG_LV_USE_GPU_NXP_PXP -# else -# define LV_USE_GPU_NXP_PXP 0 -# endif + #ifdef CONFIG_LV_USE_GPU_NXP_PXP + #define LV_USE_GPU_NXP_PXP CONFIG_LV_USE_GPU_NXP_PXP + #else + #define LV_USE_GPU_NXP_PXP 0 + #endif #endif #if LV_USE_GPU_NXP_PXP -/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS - * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. - *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() - */ -#ifndef LV_USE_GPU_NXP_PXP_AUTO_INIT -# ifdef CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT -# define LV_USE_GPU_NXP_PXP_AUTO_INIT CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT -# else -# define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 -# endif -#endif + /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS + * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. + *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() + */ + #ifndef LV_USE_GPU_NXP_PXP_AUTO_INIT + #ifdef CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT + #define LV_USE_GPU_NXP_PXP_AUTO_INIT CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT + #else + #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 + #endif + #endif #endif /*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ #ifndef LV_USE_GPU_NXP_VG_LITE -# ifdef CONFIG_LV_USE_GPU_NXP_VG_LITE -# define LV_USE_GPU_NXP_VG_LITE CONFIG_LV_USE_GPU_NXP_VG_LITE -# else -# define LV_USE_GPU_NXP_VG_LITE 0 -# endif + #ifdef CONFIG_LV_USE_GPU_NXP_VG_LITE + #define LV_USE_GPU_NXP_VG_LITE CONFIG_LV_USE_GPU_NXP_VG_LITE + #else + #define LV_USE_GPU_NXP_VG_LITE 0 + #endif #endif -/*Use exnternal renderer*/ -#ifndef LV_USE_EXTERNAL_RENDERER -# ifdef CONFIG_LV_USE_EXTERNAL_RENDERER -# define LV_USE_EXTERNAL_RENDERER CONFIG_LV_USE_EXTERNAL_RENDERER -# else -# define LV_USE_EXTERNAL_RENDERER 0 -# endif -#endif - -/*Use SDL renderer API. Requires LV_USE_EXTERNAL_RENDERER*/ +/*Use SDL renderer API*/ #ifndef LV_USE_GPU_SDL -# ifdef CONFIG_LV_USE_GPU_SDL -# define LV_USE_GPU_SDL CONFIG_LV_USE_GPU_SDL -# else -# define LV_USE_GPU_SDL 0 -# endif + #ifdef CONFIG_LV_USE_GPU_SDL + #define LV_USE_GPU_SDL CONFIG_LV_USE_GPU_SDL + #else + #define LV_USE_GPU_SDL 0 + #endif #endif #if LV_USE_GPU_SDL -#ifndef LV_GPU_SDL_INCLUDE_PATH -# ifdef CONFIG_LV_GPU_SDL_INCLUDE_PATH -# define LV_GPU_SDL_INCLUDE_PATH CONFIG_LV_GPU_SDL_INCLUDE_PATH -# else -# define LV_GPU_SDL_INCLUDE_PATH -# endif -#endif + #ifndef LV_GPU_SDL_INCLUDE_PATH + #ifdef CONFIG_LV_GPU_SDL_INCLUDE_PATH + #define LV_GPU_SDL_INCLUDE_PATH CONFIG_LV_GPU_SDL_INCLUDE_PATH + #else + #define LV_GPU_SDL_INCLUDE_PATH + #endif + #endif + /*Texture cache size, 8MB by default*/ + #ifndef LV_GPU_SDL_LRU_SIZE + #ifdef CONFIG_LV_GPU_SDL_LRU_SIZE + #define LV_GPU_SDL_LRU_SIZE CONFIG_LV_GPU_SDL_LRU_SIZE + #else + #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) + #endif + #endif + /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ + #ifndef LV_GPU_SDL_CUSTOM_BLEND_MODE + #ifdef CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE + #define LV_GPU_SDL_CUSTOM_BLEND_MODE CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE + #else + #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) + #endif + #endif #endif /*------------- @@ -407,128 +532,128 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Enable the log module*/ #ifndef LV_USE_LOG -# ifdef CONFIG_LV_USE_LOG -# define LV_USE_LOG CONFIG_LV_USE_LOG -# else -# define LV_USE_LOG 0 -# endif + #ifdef CONFIG_LV_USE_LOG + #define LV_USE_LOG CONFIG_LV_USE_LOG + #else + #define LV_USE_LOG 0 + #endif #endif #if LV_USE_LOG -/*How important log should be added: - *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information - *LV_LOG_LEVEL_INFO Log important events - *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem - *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail - *LV_LOG_LEVEL_USER Only logs added by the user - *LV_LOG_LEVEL_NONE Do not log anything*/ -#ifndef LV_LOG_LEVEL -# ifdef CONFIG_LV_LOG_LEVEL -# define LV_LOG_LEVEL CONFIG_LV_LOG_LEVEL -# else -# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN -# endif -#endif + /*How important log should be added: + *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information + *LV_LOG_LEVEL_INFO Log important events + *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem + *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail + *LV_LOG_LEVEL_USER Only logs added by the user + *LV_LOG_LEVEL_NONE Do not log anything*/ + #ifndef LV_LOG_LEVEL + #ifdef CONFIG_LV_LOG_LEVEL + #define LV_LOG_LEVEL CONFIG_LV_LOG_LEVEL + #else + #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN + #endif + #endif -/*1: Print the log with 'printf'; - *0: User need to register a callback with `lv_log_register_print_cb()`*/ -#ifndef LV_LOG_PRINTF -# ifdef CONFIG_LV_LOG_PRINTF -# define LV_LOG_PRINTF CONFIG_LV_LOG_PRINTF -# else -# define LV_LOG_PRINTF 0 -# endif -#endif + /*1: Print the log with 'printf'; + *0: User need to register a callback with `lv_log_register_print_cb()`*/ + #ifndef LV_LOG_PRINTF + #ifdef CONFIG_LV_LOG_PRINTF + #define LV_LOG_PRINTF CONFIG_LV_LOG_PRINTF + #else + #define LV_LOG_PRINTF 0 + #endif + #endif -/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ -#ifndef LV_LOG_TRACE_MEM -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_MEM -# define LV_LOG_TRACE_MEM CONFIG_LV_LOG_TRACE_MEM -# else -# define LV_LOG_TRACE_MEM 0 -# endif -# else -# define LV_LOG_TRACE_MEM 1 -# endif -#endif -#ifndef LV_LOG_TRACE_TIMER -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_TIMER -# define LV_LOG_TRACE_TIMER CONFIG_LV_LOG_TRACE_TIMER -# else -# define LV_LOG_TRACE_TIMER 0 -# endif -# else -# define LV_LOG_TRACE_TIMER 1 -# endif -#endif -#ifndef LV_LOG_TRACE_INDEV -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_INDEV -# define LV_LOG_TRACE_INDEV CONFIG_LV_LOG_TRACE_INDEV -# else -# define LV_LOG_TRACE_INDEV 0 -# endif -# else -# define LV_LOG_TRACE_INDEV 1 -# endif -#endif -#ifndef LV_LOG_TRACE_DISP_REFR -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_DISP_REFR -# define LV_LOG_TRACE_DISP_REFR CONFIG_LV_LOG_TRACE_DISP_REFR -# else -# define LV_LOG_TRACE_DISP_REFR 0 -# endif -# else -# define LV_LOG_TRACE_DISP_REFR 1 -# endif -#endif -#ifndef LV_LOG_TRACE_EVENT -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_EVENT -# define LV_LOG_TRACE_EVENT CONFIG_LV_LOG_TRACE_EVENT -# else -# define LV_LOG_TRACE_EVENT 0 -# endif -# else -# define LV_LOG_TRACE_EVENT 1 -# endif -#endif -#ifndef LV_LOG_TRACE_OBJ_CREATE -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_OBJ_CREATE -# define LV_LOG_TRACE_OBJ_CREATE CONFIG_LV_LOG_TRACE_OBJ_CREATE -# else -# define LV_LOG_TRACE_OBJ_CREATE 0 -# endif -# else -# define LV_LOG_TRACE_OBJ_CREATE 1 -# endif -#endif -#ifndef LV_LOG_TRACE_LAYOUT -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_LAYOUT -# define LV_LOG_TRACE_LAYOUT CONFIG_LV_LOG_TRACE_LAYOUT -# else -# define LV_LOG_TRACE_LAYOUT 0 -# endif -# else -# define LV_LOG_TRACE_LAYOUT 1 -# endif -#endif -#ifndef LV_LOG_TRACE_ANIM -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_LOG_TRACE_ANIM -# define LV_LOG_TRACE_ANIM CONFIG_LV_LOG_TRACE_ANIM -# else -# define LV_LOG_TRACE_ANIM 0 -# endif -# else -# define LV_LOG_TRACE_ANIM 1 -# endif -#endif + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ + #ifndef LV_LOG_TRACE_MEM + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_MEM + #define LV_LOG_TRACE_MEM CONFIG_LV_LOG_TRACE_MEM + #else + #define LV_LOG_TRACE_MEM 0 + #endif + #else + #define LV_LOG_TRACE_MEM 1 + #endif + #endif + #ifndef LV_LOG_TRACE_TIMER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_TIMER + #define LV_LOG_TRACE_TIMER CONFIG_LV_LOG_TRACE_TIMER + #else + #define LV_LOG_TRACE_TIMER 0 + #endif + #else + #define LV_LOG_TRACE_TIMER 1 + #endif + #endif + #ifndef LV_LOG_TRACE_INDEV + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_INDEV + #define LV_LOG_TRACE_INDEV CONFIG_LV_LOG_TRACE_INDEV + #else + #define LV_LOG_TRACE_INDEV 0 + #endif + #else + #define LV_LOG_TRACE_INDEV 1 + #endif + #endif + #ifndef LV_LOG_TRACE_DISP_REFR + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_DISP_REFR + #define LV_LOG_TRACE_DISP_REFR CONFIG_LV_LOG_TRACE_DISP_REFR + #else + #define LV_LOG_TRACE_DISP_REFR 0 + #endif + #else + #define LV_LOG_TRACE_DISP_REFR 1 + #endif + #endif + #ifndef LV_LOG_TRACE_EVENT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_EVENT + #define LV_LOG_TRACE_EVENT CONFIG_LV_LOG_TRACE_EVENT + #else + #define LV_LOG_TRACE_EVENT 0 + #endif + #else + #define LV_LOG_TRACE_EVENT 1 + #endif + #endif + #ifndef LV_LOG_TRACE_OBJ_CREATE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_OBJ_CREATE + #define LV_LOG_TRACE_OBJ_CREATE CONFIG_LV_LOG_TRACE_OBJ_CREATE + #else + #define LV_LOG_TRACE_OBJ_CREATE 0 + #endif + #else + #define LV_LOG_TRACE_OBJ_CREATE 1 + #endif + #endif + #ifndef LV_LOG_TRACE_LAYOUT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_LAYOUT + #define LV_LOG_TRACE_LAYOUT CONFIG_LV_LOG_TRACE_LAYOUT + #else + #define LV_LOG_TRACE_LAYOUT 0 + #endif + #else + #define LV_LOG_TRACE_LAYOUT 1 + #endif + #endif + #ifndef LV_LOG_TRACE_ANIM + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_ANIM + #define LV_LOG_TRACE_ANIM CONFIG_LV_LOG_TRACE_ANIM + #else + #define LV_LOG_TRACE_ANIM 0 + #endif + #else + #define LV_LOG_TRACE_ANIM 1 + #endif + #endif #endif /*LV_USE_LOG*/ @@ -539,176 +664,184 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Enable asserts if an operation is failed or an invalid data is found. *If LV_USE_LOG is enabled an error message will be printed on failure*/ #ifndef LV_USE_ASSERT_NULL -# ifdef CONFIG_LV_USE_ASSERT_NULL -# define LV_USE_ASSERT_NULL CONFIG_LV_USE_ASSERT_NULL -# else -# define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ASSERT_NULL + #define LV_USE_ASSERT_NULL CONFIG_LV_USE_ASSERT_NULL + #else + #define LV_USE_ASSERT_NULL 0 + #endif + #else + #define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ + #endif #endif #ifndef LV_USE_ASSERT_MALLOC -# ifdef CONFIG_LV_USE_ASSERT_MALLOC -# define LV_USE_ASSERT_MALLOC CONFIG_LV_USE_ASSERT_MALLOC -# else -# define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ASSERT_MALLOC + #define LV_USE_ASSERT_MALLOC CONFIG_LV_USE_ASSERT_MALLOC + #else + #define LV_USE_ASSERT_MALLOC 0 + #endif + #else + #define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ + #endif #endif #ifndef LV_USE_ASSERT_STYLE -# ifdef CONFIG_LV_USE_ASSERT_STYLE -# define LV_USE_ASSERT_STYLE CONFIG_LV_USE_ASSERT_STYLE -# else -# define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ -# endif + #ifdef CONFIG_LV_USE_ASSERT_STYLE + #define LV_USE_ASSERT_STYLE CONFIG_LV_USE_ASSERT_STYLE + #else + #define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ + #endif #endif #ifndef LV_USE_ASSERT_MEM_INTEGRITY -# ifdef CONFIG_LV_USE_ASSERT_MEM_INTEGRITY -# define LV_USE_ASSERT_MEM_INTEGRITY CONFIG_LV_USE_ASSERT_MEM_INTEGRITY -# else -# define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ -# endif + #ifdef CONFIG_LV_USE_ASSERT_MEM_INTEGRITY + #define LV_USE_ASSERT_MEM_INTEGRITY CONFIG_LV_USE_ASSERT_MEM_INTEGRITY + #else + #define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ + #endif #endif #ifndef LV_USE_ASSERT_OBJ -# ifdef CONFIG_LV_USE_ASSERT_OBJ -# define LV_USE_ASSERT_OBJ CONFIG_LV_USE_ASSERT_OBJ -# else -# define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ -# endif + #ifdef CONFIG_LV_USE_ASSERT_OBJ + #define LV_USE_ASSERT_OBJ CONFIG_LV_USE_ASSERT_OBJ + #else + #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ + #endif #endif /*Add a custom handler when assert happens e.g. to restart the MCU*/ #ifndef LV_ASSERT_HANDLER_INCLUDE -# ifdef CONFIG_LV_ASSERT_HANDLER_INCLUDE -# define LV_ASSERT_HANDLER_INCLUDE CONFIG_LV_ASSERT_HANDLER_INCLUDE -# else -# define LV_ASSERT_HANDLER_INCLUDE -# endif + #ifdef CONFIG_LV_ASSERT_HANDLER_INCLUDE + #define LV_ASSERT_HANDLER_INCLUDE CONFIG_LV_ASSERT_HANDLER_INCLUDE + #else + #define LV_ASSERT_HANDLER_INCLUDE + #endif #endif #ifndef LV_ASSERT_HANDLER -# ifdef CONFIG_LV_ASSERT_HANDLER -# define LV_ASSERT_HANDLER CONFIG_LV_ASSERT_HANDLER -# else -# define LV_ASSERT_HANDLER while(1); /*Halt by default*/ -# endif + #ifdef CONFIG_LV_ASSERT_HANDLER + #define LV_ASSERT_HANDLER CONFIG_LV_ASSERT_HANDLER + #else + #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ + #endif #endif /*------------- * Others *-----------*/ -/*1: Show CPU usage and FPS count in the right bottom corner*/ +/*1: Show CPU usage and FPS count*/ #ifndef LV_USE_PERF_MONITOR -# ifdef CONFIG_LV_USE_PERF_MONITOR -# define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR -# else -# define LV_USE_PERF_MONITOR 0 -# endif + #ifdef CONFIG_LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR + #else + #define LV_USE_PERF_MONITOR 0 + #endif #endif #if LV_USE_PERF_MONITOR -#ifndef LV_USE_PERF_MONITOR_POS -# ifdef CONFIG_LV_USE_PERF_MONITOR_POS -# define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS -# else -# define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT -# endif -#endif + #ifndef LV_USE_PERF_MONITOR_POS + #ifdef CONFIG_LV_USE_PERF_MONITOR_POS + #define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS + #else + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + #endif + #endif #endif -/*1: Show the used memory and the memory fragmentation in the left bottom corner +/*1: Show the used memory and the memory fragmentation * Requires LV_MEM_CUSTOM = 0*/ #ifndef LV_USE_MEM_MONITOR -# ifdef CONFIG_LV_USE_MEM_MONITOR -# define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR -# else -# define LV_USE_MEM_MONITOR 0 -# endif -#endif -#if LV_USE_PERF_MONITOR -#ifndef LV_USE_MEM_MONITOR_POS -# ifdef CONFIG_LV_USE_MEM_MONITOR_POS -# define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS -# else -# define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT -# endif + #ifdef CONFIG_LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR + #else + #define LV_USE_MEM_MONITOR 0 + #endif #endif +#if LV_USE_MEM_MONITOR + #ifndef LV_USE_MEM_MONITOR_POS + #ifdef CONFIG_LV_USE_MEM_MONITOR_POS + #define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS + #else + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + #endif #endif /*1: Draw random colored rectangles over the redrawn areas*/ #ifndef LV_USE_REFR_DEBUG -# ifdef CONFIG_LV_USE_REFR_DEBUG -# define LV_USE_REFR_DEBUG CONFIG_LV_USE_REFR_DEBUG -# else -# define LV_USE_REFR_DEBUG 0 -# endif + #ifdef CONFIG_LV_USE_REFR_DEBUG + #define LV_USE_REFR_DEBUG CONFIG_LV_USE_REFR_DEBUG + #else + #define LV_USE_REFR_DEBUG 0 + #endif #endif /*Change the built in (v)snprintf functions*/ #ifndef LV_SPRINTF_CUSTOM -# ifdef CONFIG_LV_SPRINTF_CUSTOM -# define LV_SPRINTF_CUSTOM CONFIG_LV_SPRINTF_CUSTOM -# else -# define LV_SPRINTF_CUSTOM 0 -# endif + #ifdef CONFIG_LV_SPRINTF_CUSTOM + #define LV_SPRINTF_CUSTOM CONFIG_LV_SPRINTF_CUSTOM + #else + #define LV_SPRINTF_CUSTOM 0 + #endif #endif #if LV_SPRINTF_CUSTOM -#ifndef LV_SPRINTF_INCLUDE -# ifdef CONFIG_LV_SPRINTF_INCLUDE -# define LV_SPRINTF_INCLUDE CONFIG_LV_SPRINTF_INCLUDE -# else -# define LV_SPRINTF_INCLUDE -# endif -#endif -#ifndef lv_snprintf -# ifdef CONFIG_LV_SNPRINTF -# define lv_snprintf CONFIG_LV_SNPRINTF -# else -# define lv_snprintf snprintf -# endif -#endif -#ifndef lv_vsnprintf -# ifdef CONFIG_LV_VSNPRINTF -# define lv_vsnprintf CONFIG_LV_VSNPRINTF -# else -# define lv_vsnprintf vsnprintf -# endif -#endif + #ifndef LV_SPRINTF_INCLUDE + #ifdef CONFIG_LV_SPRINTF_INCLUDE + #define LV_SPRINTF_INCLUDE CONFIG_LV_SPRINTF_INCLUDE + #else + #define LV_SPRINTF_INCLUDE + #endif + #endif + #ifndef lv_snprintf + #ifdef CONFIG_LV_SNPRINTF + #define lv_snprintf CONFIG_LV_SNPRINTF + #else + #define lv_snprintf snprintf + #endif + #endif + #ifndef lv_vsnprintf + #ifdef CONFIG_LV_VSNPRINTF + #define lv_vsnprintf CONFIG_LV_VSNPRINTF + #else + #define lv_vsnprintf vsnprintf + #endif + #endif #else /*LV_SPRINTF_CUSTOM*/ -#ifndef LV_SPRINTF_USE_FLOAT -# ifdef CONFIG_LV_SPRINTF_USE_FLOAT -# define LV_SPRINTF_USE_FLOAT CONFIG_LV_SPRINTF_USE_FLOAT -# else -# define LV_SPRINTF_USE_FLOAT 0 -# endif -#endif + #ifndef LV_SPRINTF_USE_FLOAT + #ifdef CONFIG_LV_SPRINTF_USE_FLOAT + #define LV_SPRINTF_USE_FLOAT CONFIG_LV_SPRINTF_USE_FLOAT + #else + #define LV_SPRINTF_USE_FLOAT 0 + #endif + #endif #endif /*LV_SPRINTF_CUSTOM*/ #ifndef LV_USE_USER_DATA -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_USER_DATA -# define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA -# else -# define LV_USE_USER_DATA 0 -# endif -# else -# define LV_USE_USER_DATA 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_USER_DATA + #define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA + #else + #define LV_USE_USER_DATA 0 + #endif + #else + #define LV_USE_USER_DATA 1 + #endif #endif /*Garbage Collector settings *Used if lvgl is bound to higher level language and the memory is managed by that language*/ #ifndef LV_ENABLE_GC -# ifdef CONFIG_LV_ENABLE_GC -# define LV_ENABLE_GC CONFIG_LV_ENABLE_GC -# else -# define LV_ENABLE_GC 0 -# endif + #ifdef CONFIG_LV_ENABLE_GC + #define LV_ENABLE_GC CONFIG_LV_ENABLE_GC + #else + #define LV_ENABLE_GC 0 + #endif #endif #if LV_ENABLE_GC != 0 -#ifndef LV_GC_INCLUDE -# ifdef CONFIG_LV_GC_INCLUDE -# define LV_GC_INCLUDE CONFIG_LV_GC_INCLUDE -# else -# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -# endif -#endif + #ifndef LV_GC_INCLUDE + #ifdef CONFIG_LV_GC_INCLUDE + #define LV_GC_INCLUDE CONFIG_LV_GC_INCLUDE + #else + #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ + #endif + #endif #endif /*LV_ENABLE_GC*/ /*===================== @@ -717,116 +850,116 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*For big endian systems set to 1*/ #ifndef LV_BIG_ENDIAN_SYSTEM -# ifdef CONFIG_LV_BIG_ENDIAN_SYSTEM -# define LV_BIG_ENDIAN_SYSTEM CONFIG_LV_BIG_ENDIAN_SYSTEM -# else -# define LV_BIG_ENDIAN_SYSTEM 0 -# endif + #ifdef CONFIG_LV_BIG_ENDIAN_SYSTEM + #define LV_BIG_ENDIAN_SYSTEM CONFIG_LV_BIG_ENDIAN_SYSTEM + #else + #define LV_BIG_ENDIAN_SYSTEM 0 + #endif #endif /*Define a custom attribute to `lv_tick_inc` function*/ #ifndef LV_ATTRIBUTE_TICK_INC -# ifdef CONFIG_LV_ATTRIBUTE_TICK_INC -# define LV_ATTRIBUTE_TICK_INC CONFIG_LV_ATTRIBUTE_TICK_INC -# else -# define LV_ATTRIBUTE_TICK_INC -# endif + #ifdef CONFIG_LV_ATTRIBUTE_TICK_INC + #define LV_ATTRIBUTE_TICK_INC CONFIG_LV_ATTRIBUTE_TICK_INC + #else + #define LV_ATTRIBUTE_TICK_INC + #endif #endif /*Define a custom attribute to `lv_timer_handler` function*/ #ifndef LV_ATTRIBUTE_TIMER_HANDLER -# ifdef CONFIG_LV_ATTRIBUTE_TIMER_HANDLER -# define LV_ATTRIBUTE_TIMER_HANDLER CONFIG_LV_ATTRIBUTE_TIMER_HANDLER -# else -# define LV_ATTRIBUTE_TIMER_HANDLER -# endif + #ifdef CONFIG_LV_ATTRIBUTE_TIMER_HANDLER + #define LV_ATTRIBUTE_TIMER_HANDLER CONFIG_LV_ATTRIBUTE_TIMER_HANDLER + #else + #define LV_ATTRIBUTE_TIMER_HANDLER + #endif #endif /*Define a custom attribute to `lv_disp_flush_ready` function*/ #ifndef LV_ATTRIBUTE_FLUSH_READY -# ifdef CONFIG_LV_ATTRIBUTE_FLUSH_READY -# define LV_ATTRIBUTE_FLUSH_READY CONFIG_LV_ATTRIBUTE_FLUSH_READY -# else -# define LV_ATTRIBUTE_FLUSH_READY -# endif + #ifdef CONFIG_LV_ATTRIBUTE_FLUSH_READY + #define LV_ATTRIBUTE_FLUSH_READY CONFIG_LV_ATTRIBUTE_FLUSH_READY + #else + #define LV_ATTRIBUTE_FLUSH_READY + #endif #endif /*Required alignment size for buffers*/ #ifndef LV_ATTRIBUTE_MEM_ALIGN_SIZE -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE -# define LV_ATTRIBUTE_MEM_ALIGN_SIZE CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE -# else -# define LV_ATTRIBUTE_MEM_ALIGN_SIZE 0 -# endif -# else -# define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE + #else + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 0 + #endif + #else + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 + #endif #endif /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). * E.g. __attribute__((aligned(4)))*/ #ifndef LV_ATTRIBUTE_MEM_ALIGN -# ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN -# define LV_ATTRIBUTE_MEM_ALIGN CONFIG_LV_ATTRIBUTE_MEM_ALIGN -# else -# define LV_ATTRIBUTE_MEM_ALIGN -# endif + #ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN CONFIG_LV_ATTRIBUTE_MEM_ALIGN + #else + #define LV_ATTRIBUTE_MEM_ALIGN + #endif #endif /*Attribute to mark large constant arrays for example font's bitmaps*/ #ifndef LV_ATTRIBUTE_LARGE_CONST -# ifdef CONFIG_LV_ATTRIBUTE_LARGE_CONST -# define LV_ATTRIBUTE_LARGE_CONST CONFIG_LV_ATTRIBUTE_LARGE_CONST -# else -# define LV_ATTRIBUTE_LARGE_CONST -# endif + #ifdef CONFIG_LV_ATTRIBUTE_LARGE_CONST + #define LV_ATTRIBUTE_LARGE_CONST CONFIG_LV_ATTRIBUTE_LARGE_CONST + #else + #define LV_ATTRIBUTE_LARGE_CONST + #endif #endif -/*Complier prefix for a big array declaration in RAM*/ +/*Compiler prefix for a big array declaration in RAM*/ #ifndef LV_ATTRIBUTE_LARGE_RAM_ARRAY -# ifdef CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY -# define LV_ATTRIBUTE_LARGE_RAM_ARRAY CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY -# else -# define LV_ATTRIBUTE_LARGE_RAM_ARRAY -# endif + #ifdef CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY + #define LV_ATTRIBUTE_LARGE_RAM_ARRAY CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY + #else + #define LV_ATTRIBUTE_LARGE_RAM_ARRAY + #endif #endif /*Place performance critical functions into a faster memory (e.g RAM)*/ #ifndef LV_ATTRIBUTE_FAST_MEM -# ifdef CONFIG_LV_ATTRIBUTE_FAST_MEM -# define LV_ATTRIBUTE_FAST_MEM CONFIG_LV_ATTRIBUTE_FAST_MEM -# else -# define LV_ATTRIBUTE_FAST_MEM -# endif + #ifdef CONFIG_LV_ATTRIBUTE_FAST_MEM + #define LV_ATTRIBUTE_FAST_MEM CONFIG_LV_ATTRIBUTE_FAST_MEM + #else + #define LV_ATTRIBUTE_FAST_MEM + #endif #endif /*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ #ifndef LV_ATTRIBUTE_DMA -# ifdef CONFIG_LV_ATTRIBUTE_DMA -# define LV_ATTRIBUTE_DMA CONFIG_LV_ATTRIBUTE_DMA -# else -# define LV_ATTRIBUTE_DMA -# endif + #ifdef CONFIG_LV_ATTRIBUTE_DMA + #define LV_ATTRIBUTE_DMA CONFIG_LV_ATTRIBUTE_DMA + #else + #define LV_ATTRIBUTE_DMA + #endif #endif /*Export integer constant to binding. This macro is used with constants in the form of LV_ that *should also appear on LVGL binding API such as Micropython.*/ #ifndef LV_EXPORT_CONST_INT -# ifdef CONFIG_LV_EXPORT_CONST_INT -# define LV_EXPORT_CONST_INT CONFIG_LV_EXPORT_CONST_INT -# else -# define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ -# endif + #ifdef CONFIG_LV_EXPORT_CONST_INT + #define LV_EXPORT_CONST_INT CONFIG_LV_EXPORT_CONST_INT + #else + #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ + #endif #endif /*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ #ifndef LV_USE_LARGE_COORD -# ifdef CONFIG_LV_USE_LARGE_COORD -# define LV_USE_LARGE_COORD CONFIG_LV_USE_LARGE_COORD -# else -# define LV_USE_LARGE_COORD 0 -# endif + #ifdef CONFIG_LV_USE_LARGE_COORD + #define LV_USE_LARGE_COORD CONFIG_LV_USE_LARGE_COORD + #else + #define LV_USE_LARGE_COORD 0 + #endif #endif /*================== @@ -836,260 +969,273 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Montserrat fonts with ASCII range and some symbols using bpp = 4 *https://fonts.google.com/specimen/Montserrat*/ #ifndef LV_FONT_MONTSERRAT_8 -# ifdef CONFIG_LV_FONT_MONTSERRAT_8 -# define LV_FONT_MONTSERRAT_8 CONFIG_LV_FONT_MONTSERRAT_8 -# else -# define LV_FONT_MONTSERRAT_8 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_8 + #define LV_FONT_MONTSERRAT_8 CONFIG_LV_FONT_MONTSERRAT_8 + #else + #define LV_FONT_MONTSERRAT_8 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_10 -# ifdef CONFIG_LV_FONT_MONTSERRAT_10 -# define LV_FONT_MONTSERRAT_10 CONFIG_LV_FONT_MONTSERRAT_10 -# else -# define LV_FONT_MONTSERRAT_10 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_10 + #define LV_FONT_MONTSERRAT_10 CONFIG_LV_FONT_MONTSERRAT_10 + #else + #define LV_FONT_MONTSERRAT_10 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_12 -# ifdef CONFIG_LV_FONT_MONTSERRAT_12 -# define LV_FONT_MONTSERRAT_12 CONFIG_LV_FONT_MONTSERRAT_12 -# else -# define LV_FONT_MONTSERRAT_12 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_12 + #define LV_FONT_MONTSERRAT_12 CONFIG_LV_FONT_MONTSERRAT_12 + #else + #define LV_FONT_MONTSERRAT_12 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_14 -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_FONT_MONTSERRAT_14 -# define LV_FONT_MONTSERRAT_14 CONFIG_LV_FONT_MONTSERRAT_14 -# else -# define LV_FONT_MONTSERRAT_14 0 -# endif -# else -# define LV_FONT_MONTSERRAT_14 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_FONT_MONTSERRAT_14 + #define LV_FONT_MONTSERRAT_14 CONFIG_LV_FONT_MONTSERRAT_14 + #else + #define LV_FONT_MONTSERRAT_14 0 + #endif + #else + #define LV_FONT_MONTSERRAT_14 1 + #endif #endif #ifndef LV_FONT_MONTSERRAT_16 -# ifdef CONFIG_LV_FONT_MONTSERRAT_16 -# define LV_FONT_MONTSERRAT_16 CONFIG_LV_FONT_MONTSERRAT_16 -# else -# define LV_FONT_MONTSERRAT_16 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_16 + #define LV_FONT_MONTSERRAT_16 CONFIG_LV_FONT_MONTSERRAT_16 + #else + #define LV_FONT_MONTSERRAT_16 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_18 -# ifdef CONFIG_LV_FONT_MONTSERRAT_18 -# define LV_FONT_MONTSERRAT_18 CONFIG_LV_FONT_MONTSERRAT_18 -# else -# define LV_FONT_MONTSERRAT_18 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_18 + #define LV_FONT_MONTSERRAT_18 CONFIG_LV_FONT_MONTSERRAT_18 + #else + #define LV_FONT_MONTSERRAT_18 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_20 -# ifdef CONFIG_LV_FONT_MONTSERRAT_20 -# define LV_FONT_MONTSERRAT_20 CONFIG_LV_FONT_MONTSERRAT_20 -# else -# define LV_FONT_MONTSERRAT_20 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_20 + #define LV_FONT_MONTSERRAT_20 CONFIG_LV_FONT_MONTSERRAT_20 + #else + #define LV_FONT_MONTSERRAT_20 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_22 -# ifdef CONFIG_LV_FONT_MONTSERRAT_22 -# define LV_FONT_MONTSERRAT_22 CONFIG_LV_FONT_MONTSERRAT_22 -# else -# define LV_FONT_MONTSERRAT_22 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_22 + #define LV_FONT_MONTSERRAT_22 CONFIG_LV_FONT_MONTSERRAT_22 + #else + #define LV_FONT_MONTSERRAT_22 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_24 -# ifdef CONFIG_LV_FONT_MONTSERRAT_24 -# define LV_FONT_MONTSERRAT_24 CONFIG_LV_FONT_MONTSERRAT_24 -# else -# define LV_FONT_MONTSERRAT_24 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_24 + #define LV_FONT_MONTSERRAT_24 CONFIG_LV_FONT_MONTSERRAT_24 + #else + #define LV_FONT_MONTSERRAT_24 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_26 -# ifdef CONFIG_LV_FONT_MONTSERRAT_26 -# define LV_FONT_MONTSERRAT_26 CONFIG_LV_FONT_MONTSERRAT_26 -# else -# define LV_FONT_MONTSERRAT_26 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_26 + #define LV_FONT_MONTSERRAT_26 CONFIG_LV_FONT_MONTSERRAT_26 + #else + #define LV_FONT_MONTSERRAT_26 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_28 -# ifdef CONFIG_LV_FONT_MONTSERRAT_28 -# define LV_FONT_MONTSERRAT_28 CONFIG_LV_FONT_MONTSERRAT_28 -# else -# define LV_FONT_MONTSERRAT_28 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_28 + #define LV_FONT_MONTSERRAT_28 CONFIG_LV_FONT_MONTSERRAT_28 + #else + #define LV_FONT_MONTSERRAT_28 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_30 -# ifdef CONFIG_LV_FONT_MONTSERRAT_30 -# define LV_FONT_MONTSERRAT_30 CONFIG_LV_FONT_MONTSERRAT_30 -# else -# define LV_FONT_MONTSERRAT_30 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_30 + #define LV_FONT_MONTSERRAT_30 CONFIG_LV_FONT_MONTSERRAT_30 + #else + #define LV_FONT_MONTSERRAT_30 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_32 -# ifdef CONFIG_LV_FONT_MONTSERRAT_32 -# define LV_FONT_MONTSERRAT_32 CONFIG_LV_FONT_MONTSERRAT_32 -# else -# define LV_FONT_MONTSERRAT_32 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_32 + #define LV_FONT_MONTSERRAT_32 CONFIG_LV_FONT_MONTSERRAT_32 + #else + #define LV_FONT_MONTSERRAT_32 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_34 -# ifdef CONFIG_LV_FONT_MONTSERRAT_34 -# define LV_FONT_MONTSERRAT_34 CONFIG_LV_FONT_MONTSERRAT_34 -# else -# define LV_FONT_MONTSERRAT_34 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_34 + #define LV_FONT_MONTSERRAT_34 CONFIG_LV_FONT_MONTSERRAT_34 + #else + #define LV_FONT_MONTSERRAT_34 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_36 -# ifdef CONFIG_LV_FONT_MONTSERRAT_36 -# define LV_FONT_MONTSERRAT_36 CONFIG_LV_FONT_MONTSERRAT_36 -# else -# define LV_FONT_MONTSERRAT_36 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_36 + #define LV_FONT_MONTSERRAT_36 CONFIG_LV_FONT_MONTSERRAT_36 + #else + #define LV_FONT_MONTSERRAT_36 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_38 -# ifdef CONFIG_LV_FONT_MONTSERRAT_38 -# define LV_FONT_MONTSERRAT_38 CONFIG_LV_FONT_MONTSERRAT_38 -# else -# define LV_FONT_MONTSERRAT_38 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_38 + #define LV_FONT_MONTSERRAT_38 CONFIG_LV_FONT_MONTSERRAT_38 + #else + #define LV_FONT_MONTSERRAT_38 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_40 -# ifdef CONFIG_LV_FONT_MONTSERRAT_40 -# define LV_FONT_MONTSERRAT_40 CONFIG_LV_FONT_MONTSERRAT_40 -# else -# define LV_FONT_MONTSERRAT_40 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_40 + #define LV_FONT_MONTSERRAT_40 CONFIG_LV_FONT_MONTSERRAT_40 + #else + #define LV_FONT_MONTSERRAT_40 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_42 -# ifdef CONFIG_LV_FONT_MONTSERRAT_42 -# define LV_FONT_MONTSERRAT_42 CONFIG_LV_FONT_MONTSERRAT_42 -# else -# define LV_FONT_MONTSERRAT_42 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_42 + #define LV_FONT_MONTSERRAT_42 CONFIG_LV_FONT_MONTSERRAT_42 + #else + #define LV_FONT_MONTSERRAT_42 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_44 -# ifdef CONFIG_LV_FONT_MONTSERRAT_44 -# define LV_FONT_MONTSERRAT_44 CONFIG_LV_FONT_MONTSERRAT_44 -# else -# define LV_FONT_MONTSERRAT_44 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_44 + #define LV_FONT_MONTSERRAT_44 CONFIG_LV_FONT_MONTSERRAT_44 + #else + #define LV_FONT_MONTSERRAT_44 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_46 -# ifdef CONFIG_LV_FONT_MONTSERRAT_46 -# define LV_FONT_MONTSERRAT_46 CONFIG_LV_FONT_MONTSERRAT_46 -# else -# define LV_FONT_MONTSERRAT_46 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_46 + #define LV_FONT_MONTSERRAT_46 CONFIG_LV_FONT_MONTSERRAT_46 + #else + #define LV_FONT_MONTSERRAT_46 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_48 -# ifdef CONFIG_LV_FONT_MONTSERRAT_48 -# define LV_FONT_MONTSERRAT_48 CONFIG_LV_FONT_MONTSERRAT_48 -# else -# define LV_FONT_MONTSERRAT_48 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_48 + #define LV_FONT_MONTSERRAT_48 CONFIG_LV_FONT_MONTSERRAT_48 + #else + #define LV_FONT_MONTSERRAT_48 0 + #endif #endif /*Demonstrate special features*/ #ifndef LV_FONT_MONTSERRAT_12_SUBPX -# ifdef CONFIG_LV_FONT_MONTSERRAT_12_SUBPX -# define LV_FONT_MONTSERRAT_12_SUBPX CONFIG_LV_FONT_MONTSERRAT_12_SUBPX -# else -# define LV_FONT_MONTSERRAT_12_SUBPX 0 -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_12_SUBPX + #define LV_FONT_MONTSERRAT_12_SUBPX CONFIG_LV_FONT_MONTSERRAT_12_SUBPX + #else + #define LV_FONT_MONTSERRAT_12_SUBPX 0 + #endif #endif #ifndef LV_FONT_MONTSERRAT_28_COMPRESSED -# ifdef CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED -# define LV_FONT_MONTSERRAT_28_COMPRESSED CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED -# else -# define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ -# endif + #ifdef CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED + #define LV_FONT_MONTSERRAT_28_COMPRESSED CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED + #else + #define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ + #endif #endif #ifndef LV_FONT_DEJAVU_16_PERSIAN_HEBREW -# ifdef CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW -# define LV_FONT_DEJAVU_16_PERSIAN_HEBREW CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW -# else -# define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Perisan letters and all their forms*/ -# endif + #ifdef CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW + #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW + #else + #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ + #endif #endif #ifndef LV_FONT_SIMSUN_16_CJK -# ifdef CONFIG_LV_FONT_SIMSUN_16_CJK -# define LV_FONT_SIMSUN_16_CJK CONFIG_LV_FONT_SIMSUN_16_CJK -# else -# define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ -# endif + #ifdef CONFIG_LV_FONT_SIMSUN_16_CJK + #define LV_FONT_SIMSUN_16_CJK CONFIG_LV_FONT_SIMSUN_16_CJK + #else + #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ + #endif #endif /*Pixel perfect monospace fonts*/ #ifndef LV_FONT_UNSCII_8 -# ifdef CONFIG_LV_FONT_UNSCII_8 -# define LV_FONT_UNSCII_8 CONFIG_LV_FONT_UNSCII_8 -# else -# define LV_FONT_UNSCII_8 0 -# endif + #ifdef CONFIG_LV_FONT_UNSCII_8 + #define LV_FONT_UNSCII_8 CONFIG_LV_FONT_UNSCII_8 + #else + #define LV_FONT_UNSCII_8 0 + #endif #endif #ifndef LV_FONT_UNSCII_16 -# ifdef CONFIG_LV_FONT_UNSCII_16 -# define LV_FONT_UNSCII_16 CONFIG_LV_FONT_UNSCII_16 -# else -# define LV_FONT_UNSCII_16 0 -# endif + #ifdef CONFIG_LV_FONT_UNSCII_16 + #define LV_FONT_UNSCII_16 CONFIG_LV_FONT_UNSCII_16 + #else + #define LV_FONT_UNSCII_16 0 + #endif #endif /*Optionally declare custom fonts here. *You can use these fonts as default font too and they will be available globally. *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ #ifndef LV_FONT_CUSTOM_DECLARE -# ifdef CONFIG_LV_FONT_CUSTOM_DECLARE -# define LV_FONT_CUSTOM_DECLARE CONFIG_LV_FONT_CUSTOM_DECLARE -# else -# define LV_FONT_CUSTOM_DECLARE -# endif + #ifdef CONFIG_LV_FONT_CUSTOM_DECLARE + #define LV_FONT_CUSTOM_DECLARE CONFIG_LV_FONT_CUSTOM_DECLARE + #else + #define LV_FONT_CUSTOM_DECLARE + #endif #endif /*Always set a default font*/ #ifndef LV_FONT_DEFAULT -# ifdef CONFIG_LV_FONT_DEFAULT -# define LV_FONT_DEFAULT CONFIG_LV_FONT_DEFAULT -# else -# define LV_FONT_DEFAULT &lv_font_montserrat_14 -# endif + #ifdef CONFIG_LV_FONT_DEFAULT + #define LV_FONT_DEFAULT CONFIG_LV_FONT_DEFAULT + #else + #define LV_FONT_DEFAULT &lv_font_montserrat_14 + #endif #endif /*Enable handling large font and/or fonts with a lot of characters. *The limit depends on the font size, font face and bpp. *Compiler error will be triggered if a font needs it.*/ #ifndef LV_FONT_FMT_TXT_LARGE -# ifdef CONFIG_LV_FONT_FMT_TXT_LARGE -# define LV_FONT_FMT_TXT_LARGE CONFIG_LV_FONT_FMT_TXT_LARGE -# else -# define LV_FONT_FMT_TXT_LARGE 0 -# endif + #ifdef CONFIG_LV_FONT_FMT_TXT_LARGE + #define LV_FONT_FMT_TXT_LARGE CONFIG_LV_FONT_FMT_TXT_LARGE + #else + #define LV_FONT_FMT_TXT_LARGE 0 + #endif #endif /*Enables/disables support for compressed fonts.*/ #ifndef LV_USE_FONT_COMPRESSED -# ifdef CONFIG_LV_USE_FONT_COMPRESSED -# define LV_USE_FONT_COMPRESSED CONFIG_LV_USE_FONT_COMPRESSED -# else -# define LV_USE_FONT_COMPRESSED 0 -# endif + #ifdef CONFIG_LV_USE_FONT_COMPRESSED + #define LV_USE_FONT_COMPRESSED CONFIG_LV_USE_FONT_COMPRESSED + #else + #define LV_USE_FONT_COMPRESSED 0 + #endif #endif /*Enable subpixel rendering*/ #ifndef LV_USE_FONT_SUBPX -# ifdef CONFIG_LV_USE_FONT_SUBPX -# define LV_USE_FONT_SUBPX CONFIG_LV_USE_FONT_SUBPX -# else -# define LV_USE_FONT_SUBPX 0 -# endif + #ifdef CONFIG_LV_USE_FONT_SUBPX + #define LV_USE_FONT_SUBPX CONFIG_LV_USE_FONT_SUBPX + #else + #define LV_USE_FONT_SUBPX 0 + #endif #endif #if LV_USE_FONT_SUBPX -/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ -#ifndef LV_FONT_SUBPX_BGR -# ifdef CONFIG_LV_FONT_SUBPX_BGR -# define LV_FONT_SUBPX_BGR CONFIG_LV_FONT_SUBPX_BGR -# else -# define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ -# endif + /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ + #ifndef LV_FONT_SUBPX_BGR + #ifdef CONFIG_LV_FONT_SUBPX_BGR + #define LV_FONT_SUBPX_BGR CONFIG_LV_FONT_SUBPX_BGR + #else + #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ + #endif + #endif #endif + +/*Enable drawing placeholders when glyph dsc is not found*/ +#ifndef LV_USE_FONT_PLACEHOLDER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_FONT_PLACEHOLDER + #define LV_USE_FONT_PLACEHOLDER CONFIG_LV_USE_FONT_PLACEHOLDER + #else + #define LV_USE_FONT_PLACEHOLDER 0 + #endif + #else + #define LV_USE_FONT_PLACEHOLDER 1 + #endif #endif /*================= @@ -1103,93 +1249,93 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ * - LV_TXT_ENC_ASCII */ #ifndef LV_TXT_ENC -# ifdef CONFIG_LV_TXT_ENC -# define LV_TXT_ENC CONFIG_LV_TXT_ENC -# else -# define LV_TXT_ENC LV_TXT_ENC_UTF8 -# endif + #ifdef CONFIG_LV_TXT_ENC + #define LV_TXT_ENC CONFIG_LV_TXT_ENC + #else + #define LV_TXT_ENC LV_TXT_ENC_UTF8 + #endif #endif - /*Can break (wrap) texts on these chars*/ +/*Can break (wrap) texts on these chars*/ #ifndef LV_TXT_BREAK_CHARS -# ifdef CONFIG_LV_TXT_BREAK_CHARS -# define LV_TXT_BREAK_CHARS CONFIG_LV_TXT_BREAK_CHARS -# else -# define LV_TXT_BREAK_CHARS " ,.;:-_" -# endif + #ifdef CONFIG_LV_TXT_BREAK_CHARS + #define LV_TXT_BREAK_CHARS CONFIG_LV_TXT_BREAK_CHARS + #else + #define LV_TXT_BREAK_CHARS " ,.;:-_" + #endif #endif /*If a word is at least this long, will break wherever "prettiest" *To disable, set to a value <= 0*/ #ifndef LV_TXT_LINE_BREAK_LONG_LEN -# ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_LEN -# define LV_TXT_LINE_BREAK_LONG_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_LEN -# else -# define LV_TXT_LINE_BREAK_LONG_LEN 0 -# endif + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_LEN + #define LV_TXT_LINE_BREAK_LONG_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_LEN 0 + #endif #endif /*Minimum number of characters in a long word to put on a line before a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN -# ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN -# define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN -# else -# define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 -# endif + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN + #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 + #endif #endif /*Minimum number of characters in a long word to put on a line after a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN -# ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN -# define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN -# else -# define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 -# endif + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN + #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 + #endif #endif /*The control character to use for signalling text recoloring.*/ #ifndef LV_TXT_COLOR_CMD -# ifdef CONFIG_LV_TXT_COLOR_CMD -# define LV_TXT_COLOR_CMD CONFIG_LV_TXT_COLOR_CMD -# else -# define LV_TXT_COLOR_CMD "#" -# endif + #ifdef CONFIG_LV_TXT_COLOR_CMD + #define LV_TXT_COLOR_CMD CONFIG_LV_TXT_COLOR_CMD + #else + #define LV_TXT_COLOR_CMD "#" + #endif #endif /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ #ifndef LV_USE_BIDI -# ifdef CONFIG_LV_USE_BIDI -# define LV_USE_BIDI CONFIG_LV_USE_BIDI -# else -# define LV_USE_BIDI 0 -# endif + #ifdef CONFIG_LV_USE_BIDI + #define LV_USE_BIDI CONFIG_LV_USE_BIDI + #else + #define LV_USE_BIDI 0 + #endif #endif #if LV_USE_BIDI -/*Set the default direction. Supported values: - *`LV_BASE_DIR_LTR` Left-to-Right - *`LV_BASE_DIR_RTL` Right-to-Left - *`LV_BASE_DIR_AUTO` detect texts base direction*/ -#ifndef LV_BIDI_BASE_DIR_DEF -# ifdef CONFIG_LV_BIDI_BASE_DIR_DEF -# define LV_BIDI_BASE_DIR_DEF CONFIG_LV_BIDI_BASE_DIR_DEF -# else -# define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO -# endif -#endif + /*Set the default direction. Supported values: + *`LV_BASE_DIR_LTR` Left-to-Right + *`LV_BASE_DIR_RTL` Right-to-Left + *`LV_BASE_DIR_AUTO` detect texts base direction*/ + #ifndef LV_BIDI_BASE_DIR_DEF + #ifdef CONFIG_LV_BIDI_BASE_DIR_DEF + #define LV_BIDI_BASE_DIR_DEF CONFIG_LV_BIDI_BASE_DIR_DEF + #else + #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO + #endif + #endif #endif /*Enable Arabic/Persian processing *In these languages characters should be replaced with an other form based on their position in the text*/ #ifndef LV_USE_ARABIC_PERSIAN_CHARS -# ifdef CONFIG_LV_USE_ARABIC_PERSIAN_CHARS -# define LV_USE_ARABIC_PERSIAN_CHARS CONFIG_LV_USE_ARABIC_PERSIAN_CHARS -# else -# define LV_USE_ARABIC_PERSIAN_CHARS 0 -# endif + #ifdef CONFIG_LV_USE_ARABIC_PERSIAN_CHARS + #define LV_USE_ARABIC_PERSIAN_CHARS CONFIG_LV_USE_ARABIC_PERSIAN_CHARS + #else + #define LV_USE_ARABIC_PERSIAN_CHARS 0 + #endif #endif /*================== @@ -1199,209 +1345,225 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ #ifndef LV_USE_ARC -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_ARC -# define LV_USE_ARC CONFIG_LV_USE_ARC -# else -# define LV_USE_ARC 0 -# endif -# else -# define LV_USE_ARC 1 -# endif -#endif - -#ifndef LV_USE_ANIMIMG -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_ANIMIMG -# define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG -# else -# define LV_USE_ANIMIMG 0 -# endif -# else -# define LV_USE_ANIMIMG 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ARC + #define LV_USE_ARC CONFIG_LV_USE_ARC + #else + #define LV_USE_ARC 0 + #endif + #else + #define LV_USE_ARC 1 + #endif #endif #ifndef LV_USE_BAR -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_BAR -# define LV_USE_BAR CONFIG_LV_USE_BAR -# else -# define LV_USE_BAR 0 -# endif -# else -# define LV_USE_BAR 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BAR + #define LV_USE_BAR CONFIG_LV_USE_BAR + #else + #define LV_USE_BAR 0 + #endif + #else + #define LV_USE_BAR 1 + #endif #endif #ifndef LV_USE_BTN -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_BTN -# define LV_USE_BTN CONFIG_LV_USE_BTN -# else -# define LV_USE_BTN 0 -# endif -# else -# define LV_USE_BTN 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BTN + #define LV_USE_BTN CONFIG_LV_USE_BTN + #else + #define LV_USE_BTN 0 + #endif + #else + #define LV_USE_BTN 1 + #endif #endif #ifndef LV_USE_BTNMATRIX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_BTNMATRIX -# define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX -# else -# define LV_USE_BTNMATRIX 0 -# endif -# else -# define LV_USE_BTNMATRIX 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BTNMATRIX + #define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX + #else + #define LV_USE_BTNMATRIX 0 + #endif + #else + #define LV_USE_BTNMATRIX 1 + #endif #endif #ifndef LV_USE_CANVAS -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CANVAS -# define LV_USE_CANVAS CONFIG_LV_USE_CANVAS -# else -# define LV_USE_CANVAS 0 -# endif -# else -# define LV_USE_CANVAS 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CANVAS + #define LV_USE_CANVAS CONFIG_LV_USE_CANVAS + #else + #define LV_USE_CANVAS 0 + #endif + #else + #define LV_USE_CANVAS 1 + #endif #endif #ifndef LV_USE_CHECKBOX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CHECKBOX -# define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX -# else -# define LV_USE_CHECKBOX 0 -# endif -# else -# define LV_USE_CHECKBOX 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CHECKBOX + #define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX + #else + #define LV_USE_CHECKBOX 0 + #endif + #else + #define LV_USE_CHECKBOX 1 + #endif #endif #ifndef LV_USE_DROPDOWN -# ifdef CONFIG_LV_USE_DROPDOWN -# define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN -# else -# define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_DROPDOWN + #define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN + #else + #define LV_USE_DROPDOWN 0 + #endif + #else + #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + #endif #endif #ifndef LV_USE_IMG -# ifdef CONFIG_LV_USE_IMG -# define LV_USE_IMG CONFIG_LV_USE_IMG -# else -# define LV_USE_IMG 1 /*Requires: lv_label*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_IMG + #define LV_USE_IMG CONFIG_LV_USE_IMG + #else + #define LV_USE_IMG 0 + #endif + #else + #define LV_USE_IMG 1 /*Requires: lv_label*/ + #endif #endif #ifndef LV_USE_LABEL -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_LABEL -# define LV_USE_LABEL CONFIG_LV_USE_LABEL -# else -# define LV_USE_LABEL 0 -# endif -# else -# define LV_USE_LABEL 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LABEL + #define LV_USE_LABEL CONFIG_LV_USE_LABEL + #else + #define LV_USE_LABEL 0 + #endif + #else + #define LV_USE_LABEL 1 + #endif #endif #if LV_USE_LABEL -#ifndef LV_LABEL_TEXT_SELECTION -# ifdef CONFIG_LV_LABEL_TEXT_SELECTION -# define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION -# else -# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ -# endif -#endif -#ifndef LV_LABEL_LONG_TXT_HINT -# ifdef CONFIG_LV_LABEL_LONG_TXT_HINT -# define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT -# else -# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ -# endif -#endif + #ifndef LV_LABEL_TEXT_SELECTION + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LABEL_TEXT_SELECTION + #define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION + #else + #define LV_LABEL_TEXT_SELECTION 0 + #endif + #else + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #endif + #endif + #ifndef LV_LABEL_LONG_TXT_HINT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LABEL_LONG_TXT_HINT + #define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT + #else + #define LV_LABEL_LONG_TXT_HINT 0 + #endif + #else + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #endif + #endif #endif #ifndef LV_USE_LINE -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_LINE -# define LV_USE_LINE CONFIG_LV_USE_LINE -# else -# define LV_USE_LINE 0 -# endif -# else -# define LV_USE_LINE 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LINE + #define LV_USE_LINE CONFIG_LV_USE_LINE + #else + #define LV_USE_LINE 0 + #endif + #else + #define LV_USE_LINE 1 + #endif #endif #ifndef LV_USE_ROLLER -# ifdef CONFIG_LV_USE_ROLLER -# define LV_USE_ROLLER CONFIG_LV_USE_ROLLER -# else -# define LV_USE_ROLLER 1 /*Requires: lv_label*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ROLLER + #define LV_USE_ROLLER CONFIG_LV_USE_ROLLER + #else + #define LV_USE_ROLLER 0 + #endif + #else + #define LV_USE_ROLLER 1 /*Requires: lv_label*/ + #endif #endif #if LV_USE_ROLLER -#ifndef LV_ROLLER_INF_PAGES -# ifdef CONFIG_LV_ROLLER_INF_PAGES -# define LV_ROLLER_INF_PAGES CONFIG_LV_ROLLER_INF_PAGES -# else -# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ -# endif -#endif + #ifndef LV_ROLLER_INF_PAGES + #ifdef CONFIG_LV_ROLLER_INF_PAGES + #define LV_ROLLER_INF_PAGES CONFIG_LV_ROLLER_INF_PAGES + #else + #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ + #endif + #endif #endif #ifndef LV_USE_SLIDER -# ifdef CONFIG_LV_USE_SLIDER -# define LV_USE_SLIDER CONFIG_LV_USE_SLIDER -# else -# define LV_USE_SLIDER 1 /*Requires: lv_bar*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SLIDER + #define LV_USE_SLIDER CONFIG_LV_USE_SLIDER + #else + #define LV_USE_SLIDER 0 + #endif + #else + #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + #endif #endif #ifndef LV_USE_SWITCH -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_SWITCH -# define LV_USE_SWITCH CONFIG_LV_USE_SWITCH -# else -# define LV_USE_SWITCH 0 -# endif -# else -# define LV_USE_SWITCH 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SWITCH + #define LV_USE_SWITCH CONFIG_LV_USE_SWITCH + #else + #define LV_USE_SWITCH 0 + #endif + #else + #define LV_USE_SWITCH 1 + #endif #endif #ifndef LV_USE_TEXTAREA -# ifdef CONFIG_LV_USE_TEXTAREA -# define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA -# else -# define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TEXTAREA + #define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA + #else + #define LV_USE_TEXTAREA 0 + #endif + #else + #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ + #endif #endif #if LV_USE_TEXTAREA != 0 -#ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME -# ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME -# define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME -# else -# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ -# endif -#endif + #ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME + #ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #else + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ + #endif + #endif #endif #ifndef LV_USE_TABLE -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_TABLE -# define LV_USE_TABLE CONFIG_LV_USE_TABLE -# else -# define LV_USE_TABLE 0 -# endif -# else -# define LV_USE_TABLE 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TABLE + #define LV_USE_TABLE CONFIG_LV_USE_TABLE + #else + #define LV_USE_TABLE 0 + #endif + #else + #define LV_USE_TABLE 1 + #endif #endif /*================== @@ -1411,250 +1573,274 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*----------- * Widgets *----------*/ +#ifndef LV_USE_ANIMIMG + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ANIMIMG + #define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG + #else + #define LV_USE_ANIMIMG 0 + #endif + #else + #define LV_USE_ANIMIMG 1 + #endif +#endif + #ifndef LV_USE_CALENDAR -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CALENDAR -# define LV_USE_CALENDAR CONFIG_LV_USE_CALENDAR -# else -# define LV_USE_CALENDAR 0 -# endif -# else -# define LV_USE_CALENDAR 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR + #define LV_USE_CALENDAR CONFIG_LV_USE_CALENDAR + #else + #define LV_USE_CALENDAR 0 + #endif + #else + #define LV_USE_CALENDAR 1 + #endif #endif #if LV_USE_CALENDAR -#ifndef LV_CALENDAR_WEEK_STARTS_MONDAY -# ifdef CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY -# define LV_CALENDAR_WEEK_STARTS_MONDAY CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY -# else -# define LV_CALENDAR_WEEK_STARTS_MONDAY 0 -# endif -#endif -# if LV_CALENDAR_WEEK_STARTS_MONDAY -#ifndef LV_CALENDAR_DEFAULT_DAY_NAMES -# ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES -# define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES -# else -# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} -# endif -#endif -# else -#ifndef LV_CALENDAR_DEFAULT_DAY_NAMES -# ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES -# define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES -# else -# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} -# endif -#endif -# endif + #ifndef LV_CALENDAR_WEEK_STARTS_MONDAY + #ifdef CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY + #define LV_CALENDAR_WEEK_STARTS_MONDAY CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY + #else + #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 + #endif + #endif + #if LV_CALENDAR_WEEK_STARTS_MONDAY + #ifndef LV_CALENDAR_DEFAULT_DAY_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #else + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} + #endif + #endif + #else + #ifndef LV_CALENDAR_DEFAULT_DAY_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #else + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} + #endif + #endif + #endif -#ifndef LV_CALENDAR_DEFAULT_MONTH_NAMES -# ifdef CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES -# define LV_CALENDAR_DEFAULT_MONTH_NAMES CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES -# else -# define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} -# endif -#endif -#ifndef LV_USE_CALENDAR_HEADER_ARROW -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CALENDAR_HEADER_ARROW -# define LV_USE_CALENDAR_HEADER_ARROW CONFIG_LV_USE_CALENDAR_HEADER_ARROW -# else -# define LV_USE_CALENDAR_HEADER_ARROW 0 -# endif -# else -# define LV_USE_CALENDAR_HEADER_ARROW 1 -# endif -#endif -#ifndef LV_USE_CALENDAR_HEADER_DROPDOWN -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN -# define LV_USE_CALENDAR_HEADER_DROPDOWN CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN -# else -# define LV_USE_CALENDAR_HEADER_DROPDOWN 0 -# endif -# else -# define LV_USE_CALENDAR_HEADER_DROPDOWN 1 -# endif -#endif + #ifndef LV_CALENDAR_DEFAULT_MONTH_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES + #define LV_CALENDAR_DEFAULT_MONTH_NAMES CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES + #else + #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} + #endif + #endif + #ifndef LV_USE_CALENDAR_HEADER_ARROW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR_HEADER_ARROW + #define LV_USE_CALENDAR_HEADER_ARROW CONFIG_LV_USE_CALENDAR_HEADER_ARROW + #else + #define LV_USE_CALENDAR_HEADER_ARROW 0 + #endif + #else + #define LV_USE_CALENDAR_HEADER_ARROW 1 + #endif + #endif + #ifndef LV_USE_CALENDAR_HEADER_DROPDOWN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN + #define LV_USE_CALENDAR_HEADER_DROPDOWN CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN + #else + #define LV_USE_CALENDAR_HEADER_DROPDOWN 0 + #endif + #else + #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 + #endif + #endif #endif /*LV_USE_CALENDAR*/ #ifndef LV_USE_CHART -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_CHART -# define LV_USE_CHART CONFIG_LV_USE_CHART -# else -# define LV_USE_CHART 0 -# endif -# else -# define LV_USE_CHART 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CHART + #define LV_USE_CHART CONFIG_LV_USE_CHART + #else + #define LV_USE_CHART 0 + #endif + #else + #define LV_USE_CHART 1 + #endif #endif #ifndef LV_USE_COLORWHEEL -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_COLORWHEEL -# define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL -# else -# define LV_USE_COLORWHEEL 0 -# endif -# else -# define LV_USE_COLORWHEEL 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_COLORWHEEL + #define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL + #else + #define LV_USE_COLORWHEEL 0 + #endif + #else + #define LV_USE_COLORWHEEL 1 + #endif #endif #ifndef LV_USE_IMGBTN -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_IMGBTN -# define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN -# else -# define LV_USE_IMGBTN 0 -# endif -# else -# define LV_USE_IMGBTN 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_IMGBTN + #define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN + #else + #define LV_USE_IMGBTN 0 + #endif + #else + #define LV_USE_IMGBTN 1 + #endif #endif #ifndef LV_USE_KEYBOARD -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_KEYBOARD -# define LV_USE_KEYBOARD CONFIG_LV_USE_KEYBOARD -# else -# define LV_USE_KEYBOARD 0 -# endif -# else -# define LV_USE_KEYBOARD 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_KEYBOARD + #define LV_USE_KEYBOARD CONFIG_LV_USE_KEYBOARD + #else + #define LV_USE_KEYBOARD 0 + #endif + #else + #define LV_USE_KEYBOARD 1 + #endif #endif #ifndef LV_USE_LED -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_LED -# define LV_USE_LED CONFIG_LV_USE_LED -# else -# define LV_USE_LED 0 -# endif -# else -# define LV_USE_LED 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LED + #define LV_USE_LED CONFIG_LV_USE_LED + #else + #define LV_USE_LED 0 + #endif + #else + #define LV_USE_LED 1 + #endif #endif #ifndef LV_USE_LIST -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_LIST -# define LV_USE_LIST CONFIG_LV_USE_LIST -# else -# define LV_USE_LIST 0 -# endif -# else -# define LV_USE_LIST 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LIST + #define LV_USE_LIST CONFIG_LV_USE_LIST + #else + #define LV_USE_LIST 0 + #endif + #else + #define LV_USE_LIST 1 + #endif +#endif + +#ifndef LV_USE_MENU + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_MENU + #define LV_USE_MENU CONFIG_LV_USE_MENU + #else + #define LV_USE_MENU 0 + #endif + #else + #define LV_USE_MENU 1 + #endif #endif #ifndef LV_USE_METER -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_METER -# define LV_USE_METER CONFIG_LV_USE_METER -# else -# define LV_USE_METER 0 -# endif -# else -# define LV_USE_METER 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_METER + #define LV_USE_METER CONFIG_LV_USE_METER + #else + #define LV_USE_METER 0 + #endif + #else + #define LV_USE_METER 1 + #endif #endif #ifndef LV_USE_MSGBOX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_MSGBOX -# define LV_USE_MSGBOX CONFIG_LV_USE_MSGBOX -# else -# define LV_USE_MSGBOX 0 -# endif -# else -# define LV_USE_MSGBOX 1 -# endif -#endif - -#ifndef LV_USE_SPINBOX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_SPINBOX -# define LV_USE_SPINBOX CONFIG_LV_USE_SPINBOX -# else -# define LV_USE_SPINBOX 0 -# endif -# else -# define LV_USE_SPINBOX 1 -# endif -#endif - -#ifndef LV_USE_SPINNER -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_SPINNER -# define LV_USE_SPINNER CONFIG_LV_USE_SPINNER -# else -# define LV_USE_SPINNER 0 -# endif -# else -# define LV_USE_SPINNER 1 -# endif -#endif - -#ifndef LV_USE_TABVIEW -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_TABVIEW -# define LV_USE_TABVIEW CONFIG_LV_USE_TABVIEW -# else -# define LV_USE_TABVIEW 0 -# endif -# else -# define LV_USE_TABVIEW 1 -# endif -#endif - -#ifndef LV_USE_TILEVIEW -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_TILEVIEW -# define LV_USE_TILEVIEW CONFIG_LV_USE_TILEVIEW -# else -# define LV_USE_TILEVIEW 0 -# endif -# else -# define LV_USE_TILEVIEW 1 -# endif -#endif - -#ifndef LV_USE_WIN -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_WIN -# define LV_USE_WIN CONFIG_LV_USE_WIN -# else -# define LV_USE_WIN 0 -# endif -# else -# define LV_USE_WIN 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_MSGBOX + #define LV_USE_MSGBOX CONFIG_LV_USE_MSGBOX + #else + #define LV_USE_MSGBOX 0 + #endif + #else + #define LV_USE_MSGBOX 1 + #endif #endif #ifndef LV_USE_SPAN -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_SPAN -# define LV_USE_SPAN CONFIG_LV_USE_SPAN -# else -# define LV_USE_SPAN 0 -# endif -# else -# define LV_USE_SPAN 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPAN + #define LV_USE_SPAN CONFIG_LV_USE_SPAN + #else + #define LV_USE_SPAN 0 + #endif + #else + #define LV_USE_SPAN 1 + #endif #endif #if LV_USE_SPAN -/*A line text can contain maximum num of span descriptor */ -#ifndef LV_SPAN_SNIPPET_STACK_SIZE -# ifdef CONFIG_LV_SPAN_SNIPPET_STACK_SIZE -# define LV_SPAN_SNIPPET_STACK_SIZE CONFIG_LV_SPAN_SNIPPET_STACK_SIZE -# else -# define LV_SPAN_SNIPPET_STACK_SIZE 64 -# endif + /*A line text can contain maximum num of span descriptor */ + #ifndef LV_SPAN_SNIPPET_STACK_SIZE + #ifdef CONFIG_LV_SPAN_SNIPPET_STACK_SIZE + #define LV_SPAN_SNIPPET_STACK_SIZE CONFIG_LV_SPAN_SNIPPET_STACK_SIZE + #else + #define LV_SPAN_SNIPPET_STACK_SIZE 64 + #endif + #endif #endif + +#ifndef LV_USE_SPINBOX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPINBOX + #define LV_USE_SPINBOX CONFIG_LV_USE_SPINBOX + #else + #define LV_USE_SPINBOX 0 + #endif + #else + #define LV_USE_SPINBOX 1 + #endif +#endif + +#ifndef LV_USE_SPINNER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPINNER + #define LV_USE_SPINNER CONFIG_LV_USE_SPINNER + #else + #define LV_USE_SPINNER 0 + #endif + #else + #define LV_USE_SPINNER 1 + #endif +#endif + +#ifndef LV_USE_TABVIEW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TABVIEW + #define LV_USE_TABVIEW CONFIG_LV_USE_TABVIEW + #else + #define LV_USE_TABVIEW 0 + #endif + #else + #define LV_USE_TABVIEW 1 + #endif +#endif + +#ifndef LV_USE_TILEVIEW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TILEVIEW + #define LV_USE_TILEVIEW CONFIG_LV_USE_TILEVIEW + #else + #define LV_USE_TILEVIEW 0 + #endif + #else + #define LV_USE_TILEVIEW 1 + #endif +#endif + +#ifndef LV_USE_WIN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_WIN + #define LV_USE_WIN CONFIG_LV_USE_WIN + #else + #define LV_USE_WIN 0 + #endif + #else + #define LV_USE_WIN 1 + #endif #endif /*----------- @@ -1663,74 +1849,74 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*A simple, impressive and very complete theme*/ #ifndef LV_USE_THEME_DEFAULT -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_THEME_DEFAULT -# define LV_USE_THEME_DEFAULT CONFIG_LV_USE_THEME_DEFAULT -# else -# define LV_USE_THEME_DEFAULT 0 -# endif -# else -# define LV_USE_THEME_DEFAULT 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_DEFAULT + #define LV_USE_THEME_DEFAULT CONFIG_LV_USE_THEME_DEFAULT + #else + #define LV_USE_THEME_DEFAULT 0 + #endif + #else + #define LV_USE_THEME_DEFAULT 1 + #endif #endif #if LV_USE_THEME_DEFAULT -/*0: Light mode; 1: Dark mode*/ -#ifndef LV_THEME_DEFAULT_DARK -# ifdef CONFIG_LV_THEME_DEFAULT_DARK -# define LV_THEME_DEFAULT_DARK CONFIG_LV_THEME_DEFAULT_DARK -# else -# define LV_THEME_DEFAULT_DARK 0 -# endif -#endif + /*0: Light mode; 1: Dark mode*/ + #ifndef LV_THEME_DEFAULT_DARK + #ifdef CONFIG_LV_THEME_DEFAULT_DARK + #define LV_THEME_DEFAULT_DARK CONFIG_LV_THEME_DEFAULT_DARK + #else + #define LV_THEME_DEFAULT_DARK 0 + #endif + #endif -/*1: Enable grow on press*/ -#ifndef LV_THEME_DEFAULT_GROW -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_THEME_DEFAULT_GROW -# define LV_THEME_DEFAULT_GROW CONFIG_LV_THEME_DEFAULT_GROW -# else -# define LV_THEME_DEFAULT_GROW 0 -# endif -# else -# define LV_THEME_DEFAULT_GROW 1 -# endif -#endif + /*1: Enable grow on press*/ + #ifndef LV_THEME_DEFAULT_GROW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_THEME_DEFAULT_GROW + #define LV_THEME_DEFAULT_GROW CONFIG_LV_THEME_DEFAULT_GROW + #else + #define LV_THEME_DEFAULT_GROW 0 + #endif + #else + #define LV_THEME_DEFAULT_GROW 1 + #endif + #endif -/*Default transition time in [ms]*/ -#ifndef LV_THEME_DEFAULT_TRANSITION_TIME -# ifdef CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME -# define LV_THEME_DEFAULT_TRANSITION_TIME CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME -# else -# define LV_THEME_DEFAULT_TRANSITION_TIME 80 -# endif -#endif + /*Default transition time in [ms]*/ + #ifndef LV_THEME_DEFAULT_TRANSITION_TIME + #ifdef CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME + #define LV_THEME_DEFAULT_TRANSITION_TIME CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME + #else + #define LV_THEME_DEFAULT_TRANSITION_TIME 80 + #endif + #endif #endif /*LV_USE_THEME_DEFAULT*/ /*A very simple theme that is a good starting point for a custom theme*/ #ifndef LV_USE_THEME_BASIC -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_THEME_BASIC -# define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC -# else -# define LV_USE_THEME_BASIC 0 -# endif -# else -# define LV_USE_THEME_BASIC 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_BASIC + #define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC + #else + #define LV_USE_THEME_BASIC 0 + #endif + #else + #define LV_USE_THEME_BASIC 1 + #endif #endif /*A theme designed for monochrome displays*/ #ifndef LV_USE_THEME_MONO -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_THEME_MONO -# define LV_USE_THEME_MONO CONFIG_LV_USE_THEME_MONO -# else -# define LV_USE_THEME_MONO 0 -# endif -# else -# define LV_USE_THEME_MONO 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_MONO + #define LV_USE_THEME_MONO CONFIG_LV_USE_THEME_MONO + #else + #define LV_USE_THEME_MONO 0 + #endif + #else + #define LV_USE_THEME_MONO 1 + #endif #endif /*----------- @@ -1739,143 +1925,277 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*A layout similar to Flexbox in CSS.*/ #ifndef LV_USE_FLEX -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_FLEX -# define LV_USE_FLEX CONFIG_LV_USE_FLEX -# else -# define LV_USE_FLEX 0 -# endif -# else -# define LV_USE_FLEX 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_FLEX + #define LV_USE_FLEX CONFIG_LV_USE_FLEX + #else + #define LV_USE_FLEX 0 + #endif + #else + #define LV_USE_FLEX 1 + #endif #endif /*A layout similar to Grid in CSS.*/ #ifndef LV_USE_GRID -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_GRID -# define LV_USE_GRID CONFIG_LV_USE_GRID -# else -# define LV_USE_GRID 0 -# endif -# else -# define LV_USE_GRID 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_GRID + #define LV_USE_GRID CONFIG_LV_USE_GRID + #else + #define LV_USE_GRID 0 + #endif + #else + #define LV_USE_GRID 1 + #endif #endif /*--------------------- * 3rd party libraries *--------------------*/ -/*File system interfaces for common APIs - *To enable set a driver letter for that API*/ +/*File system interfaces for common APIs */ + +/*API for fopen, fread, etc*/ #ifndef LV_USE_FS_STDIO -# ifdef CONFIG_LV_USE_FS_STDIO -# define LV_USE_FS_STDIO CONFIG_LV_USE_FS_STDIO -# else -# define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/ -# endif + #ifdef CONFIG_LV_USE_FS_STDIO + #define LV_USE_FS_STDIO CONFIG_LV_USE_FS_STDIO + #else + #define LV_USE_FS_STDIO 0 + #endif +#endif +#if LV_USE_FS_STDIO + #ifndef LV_FS_STDIO_LETTER + #ifdef CONFIG_LV_FS_STDIO_LETTER + #define LV_FS_STDIO_LETTER CONFIG_LV_FS_STDIO_LETTER + #else + #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_STDIO_PATH + #ifdef CONFIG_LV_FS_STDIO_PATH + #define LV_FS_STDIO_PATH CONFIG_LV_FS_STDIO_PATH + #else + #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_STDIO_CACHE_SIZE + #ifdef CONFIG_LV_FS_STDIO_CACHE_SIZE + #define LV_FS_STDIO_CACHE_SIZE CONFIG_LV_FS_STDIO_CACHE_SIZE + #else + #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif #endif -//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ +/*API for open, read, etc*/ #ifndef LV_USE_FS_POSIX -# ifdef CONFIG_LV_USE_FS_POSIX -# define LV_USE_FS_POSIX CONFIG_LV_USE_FS_POSIX -# else -# define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/ -# endif + #ifdef CONFIG_LV_USE_FS_POSIX + #define LV_USE_FS_POSIX CONFIG_LV_USE_FS_POSIX + #else + #define LV_USE_FS_POSIX 0 + #endif +#endif +#if LV_USE_FS_POSIX + #ifndef LV_FS_POSIX_LETTER + #ifdef CONFIG_LV_FS_POSIX_LETTER + #define LV_FS_POSIX_LETTER CONFIG_LV_FS_POSIX_LETTER + #else + #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_POSIX_PATH + #ifdef CONFIG_LV_FS_POSIX_PATH + #define LV_FS_POSIX_PATH CONFIG_LV_FS_POSIX_PATH + #else + #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_POSIX_CACHE_SIZE + #ifdef CONFIG_LV_FS_POSIX_CACHE_SIZE + #define LV_FS_POSIX_CACHE_SIZE CONFIG_LV_FS_POSIX_CACHE_SIZE + #else + #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif #endif -//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */ +/*API for CreateFile, ReadFile, etc*/ #ifndef LV_USE_FS_WIN32 -# ifdef CONFIG_LV_USE_FS_WIN32 -# define LV_USE_FS_WIN32 CONFIG_LV_USE_FS_WIN32 -# else -# define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/ -# endif + #ifdef CONFIG_LV_USE_FS_WIN32 + #define LV_USE_FS_WIN32 CONFIG_LV_USE_FS_WIN32 + #else + #define LV_USE_FS_WIN32 0 + #endif +#endif +#if LV_USE_FS_WIN32 + #ifndef LV_FS_WIN32_LETTER + #ifdef CONFIG_LV_FS_WIN32_LETTER + #define LV_FS_WIN32_LETTER CONFIG_LV_FS_WIN32_LETTER + #else + #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_WIN32_PATH + #ifdef CONFIG_LV_FS_WIN32_PATH + #define LV_FS_WIN32_PATH CONFIG_LV_FS_WIN32_PATH + #else + #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_WIN32_CACHE_SIZE + #ifdef CONFIG_LV_FS_WIN32_CACHE_SIZE + #define LV_FS_WIN32_CACHE_SIZE CONFIG_LV_FS_WIN32_CACHE_SIZE + #else + #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif #endif -//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */ +/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ #ifndef LV_USE_FS_FATFS -# ifdef CONFIG_LV_USE_FS_FATFS -# define LV_USE_FS_FATFS CONFIG_LV_USE_FS_FATFS -# else -# define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/ -# endif + #ifdef CONFIG_LV_USE_FS_FATFS + #define LV_USE_FS_FATFS CONFIG_LV_USE_FS_FATFS + #else + #define LV_USE_FS_FATFS 0 + #endif +#endif +#if LV_USE_FS_FATFS + #ifndef LV_FS_FATFS_LETTER + #ifdef CONFIG_LV_FS_FATFS_LETTER + #define LV_FS_FATFS_LETTER CONFIG_LV_FS_FATFS_LETTER + #else + #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_FATFS_CACHE_SIZE + #ifdef CONFIG_LV_FS_FATFS_CACHE_SIZE + #define LV_FS_FATFS_CACHE_SIZE CONFIG_LV_FS_FATFS_CACHE_SIZE + #else + #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif #endif /*PNG decoder library*/ #ifndef LV_USE_PNG -# ifdef CONFIG_LV_USE_PNG -# define LV_USE_PNG CONFIG_LV_USE_PNG -# else -# define LV_USE_PNG 0 -# endif + #ifdef CONFIG_LV_USE_PNG + #define LV_USE_PNG CONFIG_LV_USE_PNG + #else + #define LV_USE_PNG 0 + #endif #endif /*BMP decoder library*/ #ifndef LV_USE_BMP -# ifdef CONFIG_LV_USE_BMP -# define LV_USE_BMP CONFIG_LV_USE_BMP -# else -# define LV_USE_BMP 0 -# endif + #ifdef CONFIG_LV_USE_BMP + #define LV_USE_BMP CONFIG_LV_USE_BMP + #else + #define LV_USE_BMP 0 + #endif #endif /* JPG + split JPG decoder library. * Split JPG is a custom format optimized for embedded systems. */ #ifndef LV_USE_SJPG -# ifdef CONFIG_LV_USE_SJPG -# define LV_USE_SJPG CONFIG_LV_USE_SJPG -# else -# define LV_USE_SJPG 0 -# endif + #ifdef CONFIG_LV_USE_SJPG + #define LV_USE_SJPG CONFIG_LV_USE_SJPG + #else + #define LV_USE_SJPG 0 + #endif #endif /*GIF decoder library*/ #ifndef LV_USE_GIF -# ifdef CONFIG_LV_USE_GIF -# define LV_USE_GIF CONFIG_LV_USE_GIF -# else -# define LV_USE_GIF 0 -# endif + #ifdef CONFIG_LV_USE_GIF + #define LV_USE_GIF CONFIG_LV_USE_GIF + #else + #define LV_USE_GIF 0 + #endif #endif /*QR code library*/ #ifndef LV_USE_QRCODE -# ifdef CONFIG_LV_USE_QRCODE -# define LV_USE_QRCODE CONFIG_LV_USE_QRCODE -# else -# define LV_USE_QRCODE 0 -# endif + #ifdef CONFIG_LV_USE_QRCODE + #define LV_USE_QRCODE CONFIG_LV_USE_QRCODE + #else + #define LV_USE_QRCODE 0 + #endif #endif /*FreeType library*/ #ifndef LV_USE_FREETYPE -# ifdef CONFIG_LV_USE_FREETYPE -# define LV_USE_FREETYPE CONFIG_LV_USE_FREETYPE -# else -# define LV_USE_FREETYPE 0 -# endif + #ifdef CONFIG_LV_USE_FREETYPE + #define LV_USE_FREETYPE CONFIG_LV_USE_FREETYPE + #else + #define LV_USE_FREETYPE 0 + #endif #endif #if LV_USE_FREETYPE -/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ -#ifndef LV_FREETYPE_CACHE_SIZE -# ifdef CONFIG_LV_FREETYPE_CACHE_SIZE -# define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE -# else -# define LV_FREETYPE_CACHE_SIZE (16 * 1024) -# endif -#endif + /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ + #ifndef LV_FREETYPE_CACHE_SIZE + #ifdef CONFIG_LV_FREETYPE_CACHE_SIZE + #define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE + #else + #define LV_FREETYPE_CACHE_SIZE (16 * 1024) + #endif + #endif + #if LV_FREETYPE_CACHE_SIZE >= 0 + /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ + /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ + /* if font size >= 256, must be configured as image cache */ + #ifndef LV_FREETYPE_SBIT_CACHE + #ifdef CONFIG_LV_FREETYPE_SBIT_CACHE + #define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE + #else + #define LV_FREETYPE_SBIT_CACHE 0 + #endif + #endif + /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ + /* (0:use system defaults) */ + #ifndef LV_FREETYPE_CACHE_FT_FACES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES + #define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES + #else + #define LV_FREETYPE_CACHE_FT_FACES 0 + #endif + #endif + #ifndef LV_FREETYPE_CACHE_FT_SIZES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #else + #define LV_FREETYPE_CACHE_FT_SIZES 0 + #endif + #endif + #endif #endif /*Rlottie library*/ #ifndef LV_USE_RLOTTIE -# ifdef CONFIG_LV_USE_RLOTTIE -# define LV_USE_RLOTTIE CONFIG_LV_USE_RLOTTIE -# else -# define LV_USE_RLOTTIE 0 -# endif + #ifdef CONFIG_LV_USE_RLOTTIE + #define LV_USE_RLOTTIE CONFIG_LV_USE_RLOTTIE + #else + #define LV_USE_RLOTTIE 0 + #endif +#endif + +/*FFmpeg library for image decoding and playing videos + *Supports all major image formats so do not enable other image decoder with it*/ +#ifndef LV_USE_FFMPEG + #ifdef CONFIG_LV_USE_FFMPEG + #define LV_USE_FFMPEG CONFIG_LV_USE_FFMPEG + #else + #define LV_USE_FFMPEG 0 + #endif +#endif +#if LV_USE_FFMPEG + /*Dump input information to stderr*/ + #ifndef LV_FFMPEG_DUMP_FORMAT + #ifdef CONFIG_LV_FFMPEG_DUMP_FORMAT + #define LV_FFMPEG_DUMP_FORMAT CONFIG_LV_FFMPEG_DUMP_FORMAT + #else + #define LV_FFMPEG_DUMP_FORMAT 0 + #endif + #endif #endif /*----------- @@ -1884,17 +2204,113 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*1: Enable API to take snapshot for object*/ #ifndef LV_USE_SNAPSHOT -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_USE_SNAPSHOT -# define LV_USE_SNAPSHOT CONFIG_LV_USE_SNAPSHOT -# else -# define LV_USE_SNAPSHOT 0 -# endif -# else -# define LV_USE_SNAPSHOT 1 -# endif + #ifdef CONFIG_LV_USE_SNAPSHOT + #define LV_USE_SNAPSHOT CONFIG_LV_USE_SNAPSHOT + #else + #define LV_USE_SNAPSHOT 0 + #endif #endif +/*1: Enable Monkey test*/ +#ifndef LV_USE_MONKEY + #ifdef CONFIG_LV_USE_MONKEY + #define LV_USE_MONKEY CONFIG_LV_USE_MONKEY + #else + #define LV_USE_MONKEY 0 + #endif +#endif + +/*1: Enable grid navigation*/ +#ifndef LV_USE_GRIDNAV + #ifdef CONFIG_LV_USE_GRIDNAV + #define LV_USE_GRIDNAV CONFIG_LV_USE_GRIDNAV + #else + #define LV_USE_GRIDNAV 0 + #endif +#endif + +/*1: Enable lv_obj fragment*/ +#ifndef LV_USE_FRAGMENT + #ifdef CONFIG_LV_USE_FRAGMENT + #define LV_USE_FRAGMENT CONFIG_LV_USE_FRAGMENT + #else + #define LV_USE_FRAGMENT 0 + #endif +#endif + +/*1: Support using images as font in label or span widgets */ +#ifndef LV_USE_IMGFONT + #ifdef CONFIG_LV_USE_IMGFONT + #define LV_USE_IMGFONT CONFIG_LV_USE_IMGFONT + #else + #define LV_USE_IMGFONT 0 + #endif +#endif + +/*1: Enable a published subscriber based messaging system */ +#ifndef LV_USE_MSG + #ifdef CONFIG_LV_USE_MSG + #define LV_USE_MSG CONFIG_LV_USE_MSG + #else + #define LV_USE_MSG 0 + #endif +#endif + +/*1: Enable Pinyin input method*/ +/*Requires: lv_keyboard*/ +#ifndef LV_USE_IME_PINYIN + #ifdef CONFIG_LV_USE_IME_PINYIN + #define LV_USE_IME_PINYIN CONFIG_LV_USE_IME_PINYIN + #else + #define LV_USE_IME_PINYIN 0 + #endif +#endif +#if LV_USE_IME_PINYIN + /*1: Use default thesaurus*/ + /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ + #ifndef LV_IME_PINYIN_USE_DEFAULT_DICT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT + #define LV_IME_PINYIN_USE_DEFAULT_DICT CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT + #else + #define LV_IME_PINYIN_USE_DEFAULT_DICT 0 + #endif + #else + #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 + #endif + #endif + /*Set the maximum number of candidate panels that can be displayed*/ + /*This needs to be adjusted according to the size of the screen*/ + #ifndef LV_IME_PINYIN_CAND_TEXT_NUM + #ifdef CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM + #define LV_IME_PINYIN_CAND_TEXT_NUM CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM + #else + #define LV_IME_PINYIN_CAND_TEXT_NUM 6 + #endif + #endif + + /*Use 9 key input(k9)*/ + #ifndef LV_IME_PINYIN_USE_K9_MODE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_IME_PINYIN_USE_K9_MODE + #define LV_IME_PINYIN_USE_K9_MODE CONFIG_LV_IME_PINYIN_USE_K9_MODE + #else + #define LV_IME_PINYIN_USE_K9_MODE 0 + #endif + #else + #define LV_IME_PINYIN_USE_K9_MODE 1 + #endif + #endif + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #ifndef LV_IME_PINYIN_K9_CAND_TEXT_NUM + #ifdef CONFIG_LV_IME_PINYIN_K9_CAND_TEXT_NUM + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM CONFIG_LV_IME_PINYIN_K9_CAND_TEXT_NUM + #else + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif + #endif + #endif // LV_IME_PINYIN_USE_K9_MODE +#endif /*================== * EXAMPLES @@ -1902,15 +2318,120 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ /*Enable the examples to be built with the library*/ #ifndef LV_BUILD_EXAMPLES -# ifdef _LV_KCONFIG_PRESENT -# ifdef CONFIG_LV_BUILD_EXAMPLES -# define LV_BUILD_EXAMPLES CONFIG_LV_BUILD_EXAMPLES -# else -# define LV_BUILD_EXAMPLES 0 -# endif -# else -# define LV_BUILD_EXAMPLES 1 -# endif + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_BUILD_EXAMPLES + #define LV_BUILD_EXAMPLES CONFIG_LV_BUILD_EXAMPLES + #else + #define LV_BUILD_EXAMPLES 0 + #endif + #else + #define LV_BUILD_EXAMPLES 1 + #endif +#endif + +/*=================== + * DEMO USAGE + ====================*/ + +/*Show some widget. It might be required to increase `LV_MEM_SIZE` */ +#ifndef LV_USE_DEMO_WIDGETS + #ifdef CONFIG_LV_USE_DEMO_WIDGETS + #define LV_USE_DEMO_WIDGETS CONFIG_LV_USE_DEMO_WIDGETS + #else + #define LV_USE_DEMO_WIDGETS 0 + #endif +#endif +#if LV_USE_DEMO_WIDGETS +#ifndef LV_DEMO_WIDGETS_SLIDESHOW + #ifdef CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #define LV_DEMO_WIDGETS_SLIDESHOW CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #else + #define LV_DEMO_WIDGETS_SLIDESHOW 0 + #endif +#endif +#endif + +/*Demonstrate the usage of encoder and keyboard*/ +#ifndef LV_USE_DEMO_KEYPAD_AND_ENCODER + #ifdef CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER + #define LV_USE_DEMO_KEYPAD_AND_ENCODER CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER + #else + #define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 + #endif +#endif + +/*Benchmark your system*/ +#ifndef LV_USE_DEMO_BENCHMARK + #ifdef CONFIG_LV_USE_DEMO_BENCHMARK + #define LV_USE_DEMO_BENCHMARK CONFIG_LV_USE_DEMO_BENCHMARK + #else + #define LV_USE_DEMO_BENCHMARK 0 + #endif +#endif +#if LV_USE_DEMO_BENCHMARK +/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ +#ifndef LV_DEMO_BENCHMARK_RGB565A8 + #ifdef CONFIG_LV_DEMO_BENCHMARK_RGB565A8 + #define LV_DEMO_BENCHMARK_RGB565A8 CONFIG_LV_DEMO_BENCHMARK_RGB565A8 + #else + #define LV_DEMO_BENCHMARK_RGB565A8 0 + #endif +#endif +#endif + +/*Stress test for LVGL*/ +#ifndef LV_USE_DEMO_STRESS + #ifdef CONFIG_LV_USE_DEMO_STRESS + #define LV_USE_DEMO_STRESS CONFIG_LV_USE_DEMO_STRESS + #else + #define LV_USE_DEMO_STRESS 0 + #endif +#endif + +/*Music player demo*/ +#ifndef LV_USE_DEMO_MUSIC + #ifdef CONFIG_LV_USE_DEMO_MUSIC + #define LV_USE_DEMO_MUSIC CONFIG_LV_USE_DEMO_MUSIC + #else + #define LV_USE_DEMO_MUSIC 0 + #endif +#endif +#if LV_USE_DEMO_MUSIC + #ifndef LV_DEMO_MUSIC_SQUARE + #ifdef CONFIG_LV_DEMO_MUSIC_SQUARE + #define LV_DEMO_MUSIC_SQUARE CONFIG_LV_DEMO_MUSIC_SQUARE + #else + #define LV_DEMO_MUSIC_SQUARE 0 + #endif + #endif + #ifndef LV_DEMO_MUSIC_LANDSCAPE + #ifdef CONFIG_LV_DEMO_MUSIC_LANDSCAPE + #define LV_DEMO_MUSIC_LANDSCAPE CONFIG_LV_DEMO_MUSIC_LANDSCAPE + #else + #define LV_DEMO_MUSIC_LANDSCAPE 0 + #endif + #endif + #ifndef LV_DEMO_MUSIC_ROUND + #ifdef CONFIG_LV_DEMO_MUSIC_ROUND + #define LV_DEMO_MUSIC_ROUND CONFIG_LV_DEMO_MUSIC_ROUND + #else + #define LV_DEMO_MUSIC_ROUND 0 + #endif + #endif + #ifndef LV_DEMO_MUSIC_LARGE + #ifdef CONFIG_LV_DEMO_MUSIC_LARGE + #define LV_DEMO_MUSIC_LARGE CONFIG_LV_DEMO_MUSIC_LARGE + #else + #define LV_DEMO_MUSIC_LARGE 0 + #endif + #endif + #ifndef LV_DEMO_MUSIC_AUTO_PLAY + #ifdef CONFIG_LV_DEMO_MUSIC_AUTO_PLAY + #define LV_DEMO_MUSIC_AUTO_PLAY CONFIG_LV_DEMO_MUSIC_AUTO_PLAY + #else + #define LV_DEMO_MUSIC_AUTO_PLAY 0 + #endif + #endif #endif @@ -1923,11 +2444,26 @@ LV_EXPORT_CONST_INT(LV_DPI_DEF); #undef _LV_KCONFIG_PRESENT -/*If running without lv_conf.h add typdesf with default value*/ + +/*Set some defines if a dependency is disabled*/ +#if LV_USE_LOG == 0 + #define LV_LOG_LEVEL LV_LOG_LEVEL_NONE + #define LV_LOG_TRACE_MEM 0 + #define LV_LOG_TRACE_TIMER 0 + #define LV_LOG_TRACE_INDEV 0 + #define LV_LOG_TRACE_DISP_REFR 0 + #define LV_LOG_TRACE_EVENT 0 + #define LV_LOG_TRACE_OBJ_CREATE 0 + #define LV_LOG_TRACE_LAYOUT 0 + #define LV_LOG_TRACE_ANIM 0 +#endif /*LV_USE_LOG*/ + + +/*If running without lv_conf.h add typedefs with default value*/ #ifdef LV_CONF_SKIP -# if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /*Disable warnings for Visual Studio*/ -# define _CRT_SECURE_NO_WARNINGS -# endif + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /*Disable warnings for Visual Studio*/ + #define _CRT_SECURE_NO_WARNINGS + #endif #endif /*defined(LV_CONF_SKIP)*/ #endif /*LV_CONF_INTERNAL_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h index d12803875..7742fe77b 100644 --- a/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h +++ b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h @@ -41,6 +41,50 @@ extern "C" { # define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) #endif +/*------------------ + * MONITOR POSITION + *-----------------*/ + +#ifdef CONFIG_LV_PERF_MONITOR_ALIGN_TOP_LEFT +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_LEFT +#elif defined(CONFIG_LV_USE_PERF_MONITOR_ALIGN_TOP_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_TOP_RIGHT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_RIGHT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_LEFT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_RIGHT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_LEFT_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_LEFT_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_RIGHT_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_RIGHT_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_CENTER) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_CENTER +#endif + +#ifdef CONFIG_LV_MEM_MONITOR_ALIGN_TOP_LEFT +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_LEFT +#elif defined(CONFIG_LV_USE_MEM_MONITOR_ALIGN_TOP_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_RIGHT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_LEFT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_RIGHT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_LEFT_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_LEFT_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_RIGHT_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_RIGHT_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_CENTER) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_CENTER +#endif + /******************** * FONT SELECTION *******************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c index ecb95840d..4e4253a6e 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c @@ -147,6 +147,7 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) if((a->var == var || var == NULL) && (a->exec_cb == exec_cb || exec_cb == NULL)) { _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); + if(a->deleted_cb != NULL) a->deleted_cb(a); lv_mem_free(a); anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in the linked list*/ @@ -177,6 +178,11 @@ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) return NULL; } +struct _lv_timer_t * lv_anim_get_timer(void) +{ + return _lv_anim_tmr; +} + uint16_t lv_anim_count_running(void) { uint16_t cnt = 0; @@ -429,6 +435,7 @@ static void anim_ready_handler(lv_anim_t * a) /*Call the callback function at the end*/ if(a->ready_cb != NULL) a->ready_cb(a); + if(a->deleted_cb != NULL) a->deleted_cb(a); lv_mem_free(a); } /*If the animation is not deleted then restart it*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h index 18317eb38..faef72787 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h @@ -40,6 +40,7 @@ typedef enum { } lv_anim_enable_t; struct _lv_anim_t; +struct _lv_timer_t; /** Get the current value during an animation*/ typedef int32_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *); @@ -65,12 +66,16 @@ typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *); /** Callback used when the animation values are relative to get the current value*/ typedef int32_t (*lv_anim_get_value_cb_t)(struct _lv_anim_t *); +/** Callback used when the animation is deleted*/ +typedef void (*lv_anim_deleted_cb_t)(struct _lv_anim_t *); + /** Describes an animation*/ typedef struct _lv_anim_t { void * var; /**ready_cb = ready_cb; } +/** + * Set a function call when the animation is deleted. + * @param a pointer to an initialized `lv_anim_t` variable + * @param deleted_cb a function call when the animation is deleted + */ +static inline void lv_anim_set_deleted_cb(lv_anim_t * a, lv_anim_deleted_cb_t deleted_cb) +{ + a->deleted_cb = deleted_cb; +} + /** * Make the animation to play back to when the forward direction is ready * @param a pointer to an initialized `lv_anim_t` variable @@ -345,6 +360,12 @@ void lv_anim_del_all(void); */ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb); +/** + * Get global animation refresher timer. + * @return pointer to the animation refresher timer. + */ +struct _lv_timer_t * lv_anim_get_timer(void); + /** * Delete an animation by getting the animated variable from `a`. * Only animations with `exec_cb` will be deleted. diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c index 7c66a9b33..c0221f7ed 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c @@ -456,6 +456,59 @@ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t alig to_align->y2 = to_align->y1 + h - 1; } +#define _LV_TRANSFORM_TRIGO_SHIFT 10 +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot) +{ + if(angle == 0 && zoom == 256) { + return; + } + + p->x -= pivot->x; + p->y -= pivot->y; + + if(angle == 0) { + p->x = (((int32_t)(p->x) * zoom) >> 8) + pivot->x; + p->y = (((int32_t)(p->y) * zoom) >> 8) + pivot->y; + return; + } + + static int32_t angle_prev = INT32_MIN; + static int32_t sinma; + static int32_t cosma; + if(angle_prev != angle) { + int32_t angle_limited = angle; + if(angle_limited > 3600) angle_limited -= 3600; + if(angle_limited < 0) angle_limited += 3600; + + int32_t angle_low = angle_limited / 10; + int32_t angle_high = angle_low + 1; + int32_t angle_rem = angle_limited - (angle_low * 10); + + int32_t s1 = lv_trigo_sin(angle_low); + int32_t s2 = lv_trigo_sin(angle_high); + + int32_t c1 = lv_trigo_sin(angle_low + 90); + int32_t c2 = lv_trigo_sin(angle_high + 90); + + sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; + cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; + sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + angle_prev = angle; + } + int32_t x = p->x; + int32_t y = p->y; + if(zoom == 256) { + p->x = ((cosma * x - sinma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + p->y = ((sinma * x + cosma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; + } + else { + p->x = (((cosma * x - sinma * y) * zoom) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->x; + p->y = (((sinma * x + cosma * y) * zoom) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->y; + } +} + + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h index 542d86bc5..137931a29 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h @@ -236,6 +236,8 @@ bool _lv_area_is_equal(const lv_area_t * a, const lv_area_t * b); */ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y); +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c index 45a043154..c4941e811 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c @@ -65,6 +65,33 @@ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data) return LV_RES_OK; } +lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data) +{ + lv_timer_t * timer = lv_timer_get_next(NULL); + lv_res_t res = LV_RES_INV; + + while(timer != NULL) { + /*Find the next timer node*/ + lv_timer_t * timer_next = lv_timer_get_next(timer); + + /*Find async timer callback*/ + if(timer->timer_cb == lv_async_timer_cb) { + lv_async_info_t * info = (lv_async_info_t *)timer->user_data; + + /*Match user function callback and user data*/ + if(info->cb == async_xcb && info->user_data == user_data) { + lv_timer_del(timer); + lv_mem_free(info); + res = LV_RES_OK; + } + } + + timer = timer_next; + } + + return res; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h index 3e6cb638d..4ad5756d9 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h @@ -43,6 +43,13 @@ typedef void (*lv_async_cb_t)(void *); */ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); +/** + * Cancel an asynchronous function call + * @param async_xcb a callback which is the task itself. + * @param user_data custom parameter + */ +lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c index b207f9d9e..3dc3ce7f1 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c @@ -339,7 +339,7 @@ static uint32_t lv_bidi_get_next_paragraph(const char * txt) /** * Get the direction of a character - * @param letter an Unicode character + * @param letter a Unicode character * @return `LV_BASE_DIR_RTL/LTR/WEAK/NEUTRAL` */ static lv_base_dir_t lv_bidi_get_letter_dir(uint32_t letter) @@ -352,7 +352,7 @@ static lv_base_dir_t lv_bidi_get_letter_dir(uint32_t letter) } /** * Tell whether a character is weak or not - * @param letter an Unicode character + * @param letter a Unicode character * @return true/false */ static bool lv_bidi_letter_is_weak(uint32_t letter) @@ -371,7 +371,7 @@ static bool lv_bidi_letter_is_weak(uint32_t letter) } /** * Tell whether a character is RTL or not - * @param letter an Unicode character + * @param letter a Unicode character * @return true/false */ static bool lv_bidi_letter_is_rtl(uint32_t letter) @@ -389,7 +389,7 @@ static bool lv_bidi_letter_is_rtl(uint32_t letter) /** * Tell whether a character is neutral or not - * @param letter an Unicode character + * @param letter a Unicode character * @return true/false */ static bool lv_bidi_letter_is_neutral(uint32_t letter) diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h index 37445cc5f..2cc92f277 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h @@ -23,10 +23,6 @@ extern "C" { #error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)" #endif -#if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0 -#error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h" -#endif - #if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0 #error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h" #endif @@ -444,9 +440,9 @@ LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_co { lv_color_t ret; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 +#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 && LV_COLOR_MIX_ROUND_OFS == 0 /*Source: https://stackoverflow.com/a/50012418/1999969*/ - mix = (mix + 4) >> 3; + mix = (uint32_t)((uint32_t)mix + 4) >> 3; uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & 0x7E0F81F; /*0b00000111111000001111100000011111*/ uint32_t fg = (uint32_t)((uint32_t)c1.full | ((uint32_t)c1.full << 16)) & 0x7E0F81F; @@ -676,7 +672,7 @@ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8); lv_color_hsv_t lv_color_to_hsv(lv_color_t color); /** - * Just a wrapper around LV_COLOR_CHROMA_KEY because it might be more convenient to use a function is some cases + * Just a wrapper around LV_COLOR_CHROMA_KEY because it might be more convenient to use a function in some cases * @return LV_COLOR_CHROMA_KEY */ static inline lv_color_t lv_color_chroma_key(void) diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c index 5a7afc59a..52f3ce07d 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c @@ -95,6 +95,8 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo file_p->cache = lv_mem_alloc(sizeof(lv_fs_file_cache_t)); LV_ASSERT_MALLOC(file_p->cache); lv_memset_00(file_p->cache, sizeof(lv_fs_file_cache_t)); + file_p->cache->start = UINT32_MAX; /*Set an invalid range by default*/ + file_p->cache->end = UINT32_MAX - 1; } return LV_FS_RES_OK; @@ -138,40 +140,38 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t if(start <= file_position && file_position < end) { /* Data can be read from cache buffer */ - uint16_t buffer_offset = file_position - start; - uint16_t buffer_remaining_length = buffer_size - buffer_offset; + uint32_t buffer_remaining_length = LV_MIN((uint32_t)buffer_size - buffer_offset, (uint32_t)end - file_position); if(btr <= buffer_remaining_length) { /*Data is in cache buffer, and buffer end not reached, no need to read from FS*/ lv_memcpy(buf, buffer + buffer_offset, btr); + *br = btr; } else { /*First part of data is in cache buffer, but we need to read rest of data from FS*/ lv_memcpy(buf, buffer + buffer_offset, buffer_remaining_length); + uint32_t bytes_read_to_buffer = 0; if(btr > buffer_size) { /*If remaining data chuck is bigger than buffer size, then do not use cache, instead read it directly from FS*/ res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)(buf + buffer_remaining_length), - btr - buffer_remaining_length, br); + btr - buffer_remaining_length, &bytes_read_to_buffer); } else { /*If remaining data chunk is smaller than buffer size, then read into cache buffer*/ - uint32_t bytes_read_to_buffer = 0; - - /*Read into cache buffer:*/ res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer); - file_p->cache->start = file_p->cache->end + 1; + file_p->cache->start = file_p->cache->end; file_p->cache->end = file_p->cache->start + bytes_read_to_buffer; - uint16_t data_chunk_remaining = btr - buffer_remaining_length; - memcpy(buf + buffer_remaining_length, buffer, data_chunk_remaining); + uint16_t data_chunk_remaining = LV_MIN(btr - buffer_remaining_length, bytes_read_to_buffer); + lv_memcpy(buf + buffer_remaining_length, buffer, data_chunk_remaining); } + *br = LV_MIN(buffer_remaining_length + bytes_read_to_buffer, btr); } } else { /*Data is not in cache buffer*/ - if(btr > buffer_size) { /*If bigger data is requested, then do not use cache, instead read it directly*/ res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buf, btr, br); @@ -189,13 +189,14 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t file_p->cache->start = file_position; file_p->cache->end = file_p->cache->start + bytes_read_to_buffer; - memcpy(buf, buffer, btr); + *br = LV_MIN(btr, bytes_read_to_buffer); + lv_memcpy(buf, buffer, *br); + } } if(res == LV_FS_RES_OK) { - *br = btr; - file_p->cache->file_position += btr; + file_p->cache->file_position += *br; } return res; diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h index 0a9b24104..9f65e1b2a 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h @@ -176,8 +176,8 @@ lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * Write into a file * @param file_p pointer to a lv_fs_file_t variable * @param buf pointer to a buffer with the bytes to write - * @param btr Bytes To Write - * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h index 7551252a5..9d7d1bb92 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h @@ -59,7 +59,8 @@ extern "C" { LV_DISPATCH(f, void * , _lv_theme_default_styles) \ LV_DISPATCH(f, void * , _lv_theme_basic_styles) \ LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1) \ - LV_DISPATCH(f, uint8_t * , _lv_grad_cache_mem) + LV_DISPATCH(f, uint8_t * , _lv_grad_cache_mem) \ + LV_DISPATCH(f, uint8_t * , _lv_style_custom_prop_flag_lookup_table) #define LV_DEFINE_ROOT(root_type, root_name) root_type root_name; #define LV_ROOTS LV_ITERATE_ROOTS(LV_DEFINE_ROOT) diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c index c84647ccf..e7582316b 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c @@ -286,7 +286,7 @@ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) } /** - * Return with the pointer of the previous node after 'n_act' + * Return with the pointer of the previous node before 'n_act' * @param ll_p pointer to linked list * @param n_act pointer a node * @return pointer to the previous node diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c index 63441d6a4..d79463f2b 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c @@ -112,12 +112,29 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * } } -void lv_log(const char * buf) +void lv_log(const char * format, ...) { + if(LV_LOG_LEVEL >= LV_LOG_LEVEL_NONE) return; /* disable log */ + + va_list args; + va_start(args, format); + #if LV_LOG_PRINTF - puts(buf); + vprintf(format, args); +#else + if(custom_print_cb) { + char buf[512]; +#if LV_SPRINTF_CUSTOM + lv_vsnprintf(buf, sizeof(buf), format, args); +#else + lv_vaformat_t vaf = {format, &args}; + lv_snprintf(buf, sizeof(buf), "%pV", (void *)&vaf); #endif - if(custom_print_cb) custom_print_cb(buf); + custom_print_cb(buf); + } +#endif + + va_end(args); } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h index fa6f5ac6b..9a009930d 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h @@ -66,9 +66,10 @@ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb); /** * Print a log message via `printf` if enabled with `LV_LOG_PRINTF` in `lv_conf.h` * and/or a print callback if registered with `lv_log_register_print_cb` - * @param buf a string message to print + * @param format printf-like format string + * @param ... parameters for `format` */ -void lv_log(const char * buf); +void lv_log(const char * format, ...) LV_FORMAT_ATTRIBUTE(1, 2); /** * Add a log @@ -125,6 +126,14 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, # endif #endif +#ifndef LV_LOG +# if LV_LOG_LEVEL < LV_LOG_LEVEL_NONE +# define LV_LOG(...) lv_log(__VA_ARGS__) +# else +# define LV_LOG(...) do {} while(0) +# endif +#endif + #else /*LV_USE_LOG*/ /*Do nothing if `LV_USE_LOG 0`*/ @@ -134,6 +143,8 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, #define LV_LOG_WARN(...) do {}while(0) #define LV_LOG_ERROR(...) do {}while(0) #define LV_LOG_USER(...) do {}while(0) +#define LV_LOG(...) do {}while(0) + #endif /*LV_USE_LOG*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c index 0dcbc4415..6ff83903e 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c @@ -48,13 +48,6 @@ static int lv_lru_cmp_keys(lv_lru_item_t * item, const void * key, uint32_t key_ /** remove an item and push it to the free items queue */ static void lv_lru_remove_item(lv_lru_t * cache, lv_lru_item_t * prev, lv_lru_item_t * item, uint32_t hash_index); -/** - * remove the least recently used item - * - * @todo we can optimise this by finding the n lru items, where n = required_space / average_length - */ -static void lv_lru_remove_lru_item(lv_lru_t * cache); - /** pop an existing item off the free queue, or create a new one */ static lv_lru_item_t * lv_lru_pop_or_create_item(lv_lru_t * cache); @@ -152,7 +145,7 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v // see if the key already exists uint32_t hash_index = lv_lru_hash(cache, key, key_length); - size_t required = 0; + int required = 0; lv_lru_item_t * item = NULL, *prev = NULL; item = cache->items[hash_index]; @@ -163,7 +156,7 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v if(item) { // update the value and value_lengths - required = (size_t)(value_length - item->value_length); + required = (int)(value_length - item->value_length); cache->value_free(item->value); item->value = value; item->value_length = value_length; @@ -177,7 +170,7 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v memcpy(item->key, key, key_length); item->value_length = value_length; item->key_length = key_length; - required = (size_t) value_length; + required = (int) value_length; if(prev) prev->next = item; @@ -241,6 +234,34 @@ lv_lru_res_t lv_lru_remove(lv_lru_t * cache, const void * key, size_t key_size) return LV_LRU_OK; } +void lv_lru_remove_lru_item(lv_lru_t * cache) +{ + lv_lru_item_t * min_item = NULL, *min_prev = NULL; + lv_lru_item_t * item = NULL, *prev = NULL; + uint32_t i = 0, min_index = -1; + uint64_t min_access_count = -1; + + for(; i < cache->hash_table_size; i++) { + item = cache->items[i]; + prev = NULL; + + while(item) { + if(item->access_count < min_access_count || (int64_t) min_access_count == -1) { + min_access_count = item->access_count; + min_item = item; + min_prev = prev; + min_index = i; + } + prev = item; + item = item->next; + } + } + + if(min_item) { + lv_lru_remove_item(cache, min_prev, min_item, min_index); + } +} + /********************** * STATIC FUNCTIONS **********************/ @@ -282,18 +303,22 @@ static uint32_t lv_lru_hash(lv_lru_t * cache, const void * key, uint32_t key_len static int lv_lru_cmp_keys(lv_lru_item_t * item, const void * key, uint32_t key_length) { - if(key_length != item->key_length) + if(key_length != item->key_length) { return 1; - else + } + else { return memcmp(key, item->key, key_length); + } } static void lv_lru_remove_item(lv_lru_t * cache, lv_lru_item_t * prev, lv_lru_item_t * item, uint32_t hash_index) { - if(prev) + if(prev) { prev->next = item->next; - else + } + else { cache->items[hash_index] = (lv_lru_item_t *) item->next; + } // free memory and update the free memory counter cache->free_memory += item->value_length; @@ -306,33 +331,6 @@ static void lv_lru_remove_item(lv_lru_t * cache, lv_lru_item_t * prev, lv_lru_it cache->free_items = item; } -static void lv_lru_remove_lru_item(lv_lru_t * cache) -{ - lv_lru_item_t * min_item = NULL, *min_prev = NULL; - lv_lru_item_t * item = NULL, *prev = NULL; - uint32_t i = 0, min_index = -1; - uint64_t min_access_count = -1; - - for(; i < cache->hash_table_size; i++) { - item = cache->items[i]; - prev = NULL; - - while(item) { - if(item->access_count < min_access_count || (int64_t) min_access_count == -1) { - min_access_count = item->access_count; - min_item = item; - min_prev = prev; - min_index = i; - } - prev = item; - item = item->next; - } - } - - if(min_item) - lv_lru_remove_item(cache, min_prev, min_item, min_index); -} - static lv_lru_item_t * lv_lru_pop_or_create_item(lv_lru_t * cache) { lv_lru_item_t * item = NULL; diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h index 07d3bd361..2d0134e5c 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h @@ -71,6 +71,12 @@ lv_lru_res_t lv_lru_get(lv_lru_t * cache, const void * key, size_t key_size, voi lv_lru_res_t lv_lru_remove(lv_lru_t * cache, const void * key, size_t key_size); +/** + * remove the least recently used item + * + * @todo we can optimise this by finding the n lru items, where n = required_space / average_length + */ +void lv_lru_remove_lru_item(lv_lru_t * cache); /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c index 2144a50ca..bfb3934b2 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c @@ -235,8 +235,11 @@ int64_t lv_pow(int64_t base, int8_t exp) */ int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) { - if(x >= max_in) return max_out; - if(x <= min_in) return min_out; + if(max_in >= min_in && x >= max_in) return max_out; + if(max_in >= min_in && x <= min_in) return min_out; + + if(max_in <= min_in && x <= max_in) return max_out; + if(max_in <= min_in && x >= min_in) return min_out; /** * The equation should be: diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c index 91d50678b..b7c602f7a 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c @@ -55,6 +55,8 @@ **********************/ #if LV_MEM_CUSTOM == 0 static lv_tlsf_t tlsf; + static uint32_t cur_used; + static uint32_t max_used; #endif static uint32_t zero_mem = ZERO_MEM_SENTINEL; /*Give the address of this variable if 0 byte should be allocated*/ @@ -135,12 +137,14 @@ void * lv_mem_alloc(size_t size) #endif if(alloc == NULL) { - LV_LOG_ERROR("couldn't allocate memory (%lu bytes)", (unsigned long)size); + LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size); +#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO lv_mem_monitor_t mon; lv_mem_monitor(&mon); - LV_LOG_ERROR("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", - (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, - (int)mon.free_biggest_size); + LV_LOG_INFO("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", + (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, + (int)mon.free_biggest_size); +#endif } #if LV_MEM_ADD_JUNK else { @@ -148,7 +152,13 @@ void * lv_mem_alloc(size_t size) } #endif - MEM_TRACE("allocated at %p", alloc); + if(alloc) { +#if LV_MEM_CUSTOM == 0 + cur_used += size; + max_used = LV_MAX(cur_used, max_used); +#endif + MEM_TRACE("allocated at %p", alloc); + } return alloc; } @@ -166,7 +176,9 @@ void lv_mem_free(void * data) # if LV_MEM_ADD_JUNK lv_memset(data, 0xbb, lv_tlsf_block_size(data)); # endif - lv_tlsf_free(tlsf, data); + size_t size = lv_tlsf_free(tlsf, data); + if(cur_used > size) cur_used -= size; + else cur_used = 0; #else LV_MEM_CUSTOM_FREE(data); #endif @@ -250,6 +262,8 @@ void lv_mem_monitor(lv_mem_monitor_t * mon_p) mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/ } + mon_p->max_used = max_used; + MEM_TRACE("finished"); #endif } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c index 8b065a8e6..419c29e48 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c @@ -7,7 +7,10 @@ * INCLUDES *********************/ #include "lv_style.h" +#include "../misc/lv_gc.h" #include "../misc/lv_mem.h" +#include "lv_assert.h" +#include "lv_types.h" /********************* * DEFINES @@ -21,14 +24,121 @@ * STATIC PROTOTYPES **********************/ +static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value, + void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *)); +static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, + lv_style_value_t * value_storage); +static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, + lv_style_value_t * value_storage); + /********************** * GLOBAL VARIABLES **********************/ +const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PROPS] = { + [LV_STYLE_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_MIN_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_MAX_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_MIN_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_MAX_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_X] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_Y] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_ALIGN] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_TRANSFORM_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_TRANSFORM_HEIGHT] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_TRANSLATE_X] = LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + [LV_STYLE_TRANSLATE_Y] = LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + [LV_STYLE_TRANSFORM_ZOOM] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYER_REFR, + [LV_STYLE_TRANSFORM_ANGLE] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYER_REFR, + + [LV_STYLE_PAD_TOP] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_PAD_BOTTOM] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_PAD_LEFT] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_PAD_RIGHT] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_PAD_ROW] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_PAD_COLUMN] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + + [LV_STYLE_BG_COLOR] = 0, + [LV_STYLE_BG_OPA] = 0, + [LV_STYLE_BG_GRAD_COLOR] = 0, + [LV_STYLE_BG_GRAD_DIR] = 0, + [LV_STYLE_BG_MAIN_STOP] = 0, + [LV_STYLE_BG_GRAD_STOP] = 0, + [LV_STYLE_BG_GRAD] = 0, + [LV_STYLE_BG_DITHER_MODE] = 0, + + [LV_STYLE_BG_IMG_SRC] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_BG_IMG_OPA] = 0, + [LV_STYLE_BG_IMG_RECOLOR] = 0, + [LV_STYLE_BG_IMG_RECOLOR_OPA] = 0, + [LV_STYLE_BG_IMG_TILED] = 0, + + [LV_STYLE_BORDER_COLOR] = 0, + [LV_STYLE_BORDER_OPA] = 0, + [LV_STYLE_BORDER_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_BORDER_SIDE] = 0, + [LV_STYLE_BORDER_POST] = 0, + + [LV_STYLE_OUTLINE_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_OUTLINE_COLOR] = 0, + [LV_STYLE_OUTLINE_OPA] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_OUTLINE_PAD] = LV_STYLE_PROP_EXT_DRAW, + + [LV_STYLE_SHADOW_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_OFS_X] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_OFS_Y] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_SPREAD] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_COLOR] = 0, + [LV_STYLE_SHADOW_OPA] = LV_STYLE_PROP_EXT_DRAW, + + [LV_STYLE_IMG_OPA] = 0, + [LV_STYLE_IMG_RECOLOR] = 0, + [LV_STYLE_IMG_RECOLOR_OPA] = 0, + + [LV_STYLE_LINE_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_LINE_DASH_WIDTH] = 0, + [LV_STYLE_LINE_DASH_GAP] = 0, + [LV_STYLE_LINE_ROUNDED] = 0, + [LV_STYLE_LINE_COLOR] = 0, + [LV_STYLE_LINE_OPA] = 0, + + [LV_STYLE_ARC_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_ARC_ROUNDED] = 0, + [LV_STYLE_ARC_COLOR] = 0, + [LV_STYLE_ARC_OPA] = 0, + [LV_STYLE_ARC_IMG_SRC] = 0, + + [LV_STYLE_TEXT_COLOR] = LV_STYLE_PROP_INHERIT, + [LV_STYLE_TEXT_OPA] = LV_STYLE_PROP_INHERIT, + [LV_STYLE_TEXT_FONT] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_TEXT_LETTER_SPACE] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_TEXT_LINE_SPACE] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_TEXT_DECOR] = LV_STYLE_PROP_INHERIT, + [LV_STYLE_TEXT_ALIGN] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + + [LV_STYLE_RADIUS] = 0, + [LV_STYLE_CLIP_CORNER] = 0, + [LV_STYLE_OPA] = LV_STYLE_PROP_LAYER_REFR, + [LV_STYLE_COLOR_FILTER_DSC] = LV_STYLE_PROP_INHERIT, + [LV_STYLE_COLOR_FILTER_OPA] = LV_STYLE_PROP_INHERIT, + [LV_STYLE_ANIM_TIME] = 0, + [LV_STYLE_ANIM_SPEED] = 0, + [LV_STYLE_TRANSITION] = 0, + [LV_STYLE_BLEND_MODE] = LV_STYLE_PROP_LAYER_REFR, + [LV_STYLE_LAYOUT] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_BASE_DIR] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, +}; + +uint32_t _lv_style_custom_prop_flag_lookup_table_size = 0; + /********************** * STATIC VARIABLES **********************/ +static uint16_t last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP; +static const lv_style_value_t null_style_value = { .num = 0 }; + /********************** * MACROS **********************/ @@ -55,7 +165,7 @@ void lv_style_reset(lv_style_t * style) { LV_ASSERT_STYLE(style); - if(style->is_const) { + if(style->prop1 == LV_STYLE_PROP_ANY) { LV_LOG_ERROR("Cannot reset const style"); return; } @@ -67,18 +177,52 @@ void lv_style_reset(lv_style_t * style) #endif } -lv_style_prop_t lv_style_register_prop(void) +lv_style_prop_t lv_style_register_prop(uint8_t flag) { - static uint16_t act_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP; - act_id++; - return act_id; + if(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) == NULL) { + _lv_style_custom_prop_flag_lookup_table_size = 0; + last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP; + } + + if(((last_custom_prop_id + 1) & LV_STYLE_PROP_META_MASK) != 0) { + LV_LOG_ERROR("No more custom property IDs available"); + return LV_STYLE_PROP_INV; + } + + /* + * Allocate the lookup table if it's not yet available. + */ + size_t required_size = (last_custom_prop_id + 1 - _LV_STYLE_LAST_BUILT_IN_PROP); + if(_lv_style_custom_prop_flag_lookup_table_size < required_size) { + /* Round required_size up to the nearest 32-byte value */ + required_size = (required_size + 31) & ~31; + LV_ASSERT_MSG(required_size > 0, "required size has become 0?"); + uint8_t * old_p = LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table); + uint8_t * new_p = lv_mem_realloc(old_p, required_size * sizeof(uint8_t)); + if(new_p == NULL) { + LV_LOG_ERROR("Unable to allocate space for custom property lookup table"); + return LV_STYLE_PROP_INV; + } + LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) = new_p; + _lv_style_custom_prop_flag_lookup_table_size = required_size; + } + last_custom_prop_id++; + /* This should never happen - we should bail out above */ + LV_ASSERT_NULL(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)); + LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)[last_custom_prop_id - _LV_STYLE_NUM_BUILT_IN_PROPS] = flag; + return last_custom_prop_id; +} + +lv_style_prop_t lv_style_get_num_custom_props(void) +{ + return last_custom_prop_id - _LV_STYLE_LAST_BUILT_IN_PROP; } bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) { LV_ASSERT_STYLE(style); - if(style->is_const) { + if(style->prop1 == LV_STYLE_PROP_ANY) { LV_LOG_ERROR("Cannot remove prop from const style"); return false; } @@ -86,7 +230,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) if(style->prop_cnt == 0) return false; if(style->prop_cnt == 1) { - if(style->prop1 == prop) { + if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) { style->prop1 = LV_STYLE_PROP_INV; style->prop_cnt = 0; return true; @@ -98,7 +242,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) uint16_t * old_props = (uint16_t *)tmp; uint32_t i; for(i = 0; i < style->prop_cnt; i++) { - if(old_props[i] == prop) { + if(LV_STYLE_PROP_ID_MASK(old_props[i]) == prop) { lv_style_value_t * old_values = (lv_style_value_t *)style->v_p.values_and_props; if(style->prop_cnt == 2) { @@ -137,78 +281,15 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value) { - LV_ASSERT_STYLE(style); - - if(style->is_const) { - LV_LOG_ERROR("Cannot set property of constant style"); - return; - } - - if(style->prop_cnt > 1) { - uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - int32_t i; - for(i = style->prop_cnt - 1; i >= 0; i--) { - if(props[i] == prop) { - lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; - values[i] = value; - return; - } - } - - size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); - uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size); - if(values_and_props == NULL) return; - style->v_p.values_and_props = values_and_props; - - tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - props = (uint16_t *)tmp; - /*Shift all props to make place for the value before them*/ - for(i = style->prop_cnt - 1; i >= 0; i--) { - props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i]; - } - style->prop_cnt++; - - /*Go to the new position wit the props*/ - tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - props = (uint16_t *)tmp; - lv_style_value_t * values = (lv_style_value_t *)values_and_props; - - /*Set the new property and value*/ - props[style->prop_cnt - 1] = prop; - values[style->prop_cnt - 1] = value; - } - else if(style->prop_cnt == 1) { - if(style->prop1 == prop) { - style->v_p.value1 = value; - return; - } - size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); - uint8_t * values_and_props = lv_mem_alloc(size); - if(values_and_props == NULL) return; - lv_style_value_t value_tmp = style->v_p.value1; - style->v_p.values_and_props = values_and_props; - style->prop_cnt++; - - uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - lv_style_value_t * values = (lv_style_value_t *)values_and_props; - props[0] = style->prop1; - props[1] = prop; - values[0] = value_tmp; - values[1] = value; - } - else { - style->prop_cnt = 1; - style->prop1 = prop; - style->v_p.value1 = value; - } - - uint8_t group = _lv_style_get_prop_group(prop); - style->has_group |= 1 << group; + lv_style_set_prop_internal(style, prop, value, lv_style_set_prop_helper); } -lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) +void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta) +{ + lv_style_set_prop_internal(style, prop | meta, null_style_value, lv_style_set_prop_meta_helper); +} + +lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) { return lv_style_get_prop_inlined(style, prop, value); } @@ -295,6 +376,110 @@ uint8_t _lv_style_get_prop_group(lv_style_prop_t prop) return (uint8_t)group; } +uint8_t _lv_style_prop_lookup_flags(lv_style_prop_t prop) +{ + extern const uint8_t _lv_style_builtin_prop_flag_lookup_table[]; + extern uint32_t _lv_style_custom_prop_flag_lookup_table_size; + if(prop == LV_STYLE_PROP_ANY) return LV_STYLE_PROP_ALL; /*Any prop can have any flags*/ + if(prop == LV_STYLE_PROP_INV) return 0; + + if(prop < _LV_STYLE_NUM_BUILT_IN_PROPS) + return _lv_style_builtin_prop_flag_lookup_table[prop]; + prop -= _LV_STYLE_NUM_BUILT_IN_PROPS; + if(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) != NULL && prop < _lv_style_custom_prop_flag_lookup_table_size) + return LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)[prop]; + return 0; +} + /********************** * STATIC FUNCTIONS **********************/ + +static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, + lv_style_value_t * value_storage) +{ + *prop_storage = prop; + *value_storage = value; +} + +static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, + lv_style_value_t * value_storage) +{ + LV_UNUSED(value); + LV_UNUSED(value_storage); + *prop_storage = prop; /* meta is OR-ed into the prop ID already */ +} + +static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value, + void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *)) +{ + LV_ASSERT_STYLE(style); + + if(style->prop1 == LV_STYLE_PROP_ANY) { + LV_LOG_ERROR("Cannot set property of constant style"); + return; + } + + lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(prop_and_meta); + + if(style->prop_cnt > 1) { + uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint16_t * props = (uint16_t *)tmp; + int32_t i; + for(i = style->prop_cnt - 1; i >= 0; i--) { + if(LV_STYLE_PROP_ID_MASK(props[i]) == prop_id) { + lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; + value_adjustment_helper(prop_and_meta, value, &props[i], &values[i]); + return; + } + } + + size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); + uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size); + if(values_and_props == NULL) return; + style->v_p.values_and_props = values_and_props; + + tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + props = (uint16_t *)tmp; + /*Shift all props to make place for the value before them*/ + for(i = style->prop_cnt - 1; i >= 0; i--) { + props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i]; + } + style->prop_cnt++; + + /*Go to the new position wit the props*/ + tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + props = (uint16_t *)tmp; + lv_style_value_t * values = (lv_style_value_t *)values_and_props; + + /*Set the new property and value*/ + value_adjustment_helper(prop_and_meta, value, &props[style->prop_cnt - 1], &values[style->prop_cnt - 1]); + } + else if(style->prop_cnt == 1) { + if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop_id) { + value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1); + return; + } + size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); + uint8_t * values_and_props = lv_mem_alloc(size); + if(values_and_props == NULL) return; + lv_style_value_t value_tmp = style->v_p.value1; + style->v_p.values_and_props = values_and_props; + style->prop_cnt++; + + uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint16_t * props = (uint16_t *)tmp; + lv_style_value_t * values = (lv_style_value_t *)values_and_props; + props[0] = style->prop1; + values[0] = value_tmp; + value_adjustment_helper(prop_and_meta, value, &props[1], &values[1]); + } + else { + style->prop_cnt = 1; + value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1); + } + + uint8_t group = _lv_style_get_prop_group(prop_id); + style->has_group |= 1 << group; +} + diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h index 6ec97cb57..770ba1df1 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h @@ -31,13 +31,17 @@ extern "C" { #define LV_STYLE_SENTINEL_VALUE 0xAABBCCDD /** - * Flags for style properties + * Flags for style behavior + * + * The rest of the flags will have _FLAG added to their name in v9. */ -#define LV_STYLE_PROP_INHERIT (1 << 10) /*Inherited*/ -#define LV_STYLE_PROP_EXT_DRAW (1 << 11) /*Requires ext. draw size update when changed*/ -#define LV_STYLE_PROP_LAYOUT_REFR (1 << 12) /*Requires layout update when changed*/ -#define LV_STYLE_PROP_PARENT_LAYOUT_REFR (1 << 13) /*Requires layout update on parent when changed*/ -#define LV_STYLE_PROP_FILTER (1 << 14) /*Apply color filter*/ +#define LV_STYLE_PROP_FLAG_NONE (0) +#define LV_STYLE_PROP_INHERIT (1 << 0) /*Inherited*/ +#define LV_STYLE_PROP_EXT_DRAW (1 << 1) /*Requires ext. draw size update when changed*/ +#define LV_STYLE_PROP_LAYOUT_REFR (1 << 2) /*Requires layout update when changed*/ +#define LV_STYLE_PROP_PARENT_LAYOUT_REFR (1 << 3) /*Requires layout update on parent when changed*/ +#define LV_STYLE_PROP_LAYER_REFR (1 << 4) /*Affects layer handling*/ +#define LV_STYLE_PROP_ALL (0x1F) /*Indicating all flags*/ /** * Other constants @@ -46,9 +50,9 @@ extern "C" { LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE); #if LV_USE_ASSERT_STYLE -#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .sentinel = LV_STYLE_SENTINEL_VALUE, .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 } +#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .sentinel = LV_STYLE_SENTINEL_VALUE, .v_p = { .const_props = prop_array }, .has_group = 0xFF, .prop1 = LV_STYLE_PROP_ANY } #else -#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 } +#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .v_p = { .const_props = prop_array }, .has_group = 0xFF, .prop1 = LV_STYLE_PROP_ANY } #endif /** On simple system, don't waste resources on gradients */ @@ -56,6 +60,11 @@ LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE); #define LV_GRADIENT_MAX_STOPS 2 #endif +#define LV_STYLE_PROP_META_INHERIT 0x8000 +#define LV_STYLE_PROP_META_INITIAL 0x4000 +#define LV_STYLE_PROP_META_MASK (LV_STYLE_PROP_META_INHERIT | LV_STYLE_PROP_META_INITIAL) + +#define LV_STYLE_PROP_ID_MASK(prop) ((lv_style_prop_t)((prop) & ~LV_STYLE_PROP_META_MASK)) /********************** * TYPEDEFS @@ -153,126 +162,125 @@ typedef union { /** * Enumeration of all built in style properties + * + * Props are split into groups of 16. When adding a new prop to a group, ensure it does not overflow into the next one. */ typedef enum { - LV_STYLE_PROP_INV = 0, + LV_STYLE_PROP_INV = 0, /*Group 0*/ - LV_STYLE_WIDTH = 1 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_MIN_WIDTH = 2 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_MAX_WIDTH = 3 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_HEIGHT = 4 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_MIN_HEIGHT = 5 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_MAX_HEIGHT = 6 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_X = 7 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_Y = 8 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_ALIGN = 9 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_TRANSFORM_WIDTH = 10 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_TRANSFORM_HEIGHT = 11 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_TRANSLATE_X = 12 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - LV_STYLE_TRANSLATE_Y = 13 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + LV_STYLE_WIDTH = 1, + LV_STYLE_MIN_WIDTH = 2, + LV_STYLE_MAX_WIDTH = 3, + LV_STYLE_HEIGHT = 4, + LV_STYLE_MIN_HEIGHT = 5, + LV_STYLE_MAX_HEIGHT = 6, + LV_STYLE_X = 7, + LV_STYLE_Y = 8, + LV_STYLE_ALIGN = 9, + LV_STYLE_LAYOUT = 10, + LV_STYLE_RADIUS = 11, /*Group 1*/ - LV_STYLE_PAD_TOP = 16 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_BOTTOM = 17 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_LEFT = 18 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_RIGHT = 19 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_ROW = 20 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_PAD_COLUMN = 21 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_TOP = 16, + LV_STYLE_PAD_BOTTOM = 17, + LV_STYLE_PAD_LEFT = 18, + LV_STYLE_PAD_RIGHT = 19, + LV_STYLE_PAD_ROW = 20, + LV_STYLE_PAD_COLUMN = 21, + LV_STYLE_BASE_DIR = 22, + LV_STYLE_CLIP_CORNER = 23, /*Group 2*/ - LV_STYLE_BG_COLOR = 32, - LV_STYLE_BG_COLOR_FILTERED = 32 | LV_STYLE_PROP_FILTER, - LV_STYLE_BG_OPA = 33, - LV_STYLE_BG_GRAD_COLOR = 34, - LV_STYLE_BG_GRAD_COLOR_FILTERED = 34 | LV_STYLE_PROP_FILTER, - LV_STYLE_BG_GRAD_DIR = 35, - LV_STYLE_BG_MAIN_STOP = 36, - LV_STYLE_BG_GRAD_STOP = 37, - LV_STYLE_BG_GRAD = 38, - LV_STYLE_BG_DITHER_MODE = 39, - - - LV_STYLE_BG_IMG_SRC = 40 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_BG_IMG_OPA = 41, - LV_STYLE_BG_IMG_RECOLOR = 42, - LV_STYLE_BG_IMG_RECOLOR_FILTERED = 42 | LV_STYLE_PROP_FILTER, - LV_STYLE_BG_IMG_RECOLOR_OPA = 43, - LV_STYLE_BG_IMG_TILED = 44, + LV_STYLE_BG_COLOR = 32, + LV_STYLE_BG_OPA = 33, + LV_STYLE_BG_GRAD_COLOR = 34, + LV_STYLE_BG_GRAD_DIR = 35, + LV_STYLE_BG_MAIN_STOP = 36, + LV_STYLE_BG_GRAD_STOP = 37, + LV_STYLE_BG_GRAD = 38, + LV_STYLE_BG_DITHER_MODE = 39, + LV_STYLE_BG_IMG_SRC = 40, + LV_STYLE_BG_IMG_OPA = 41, + LV_STYLE_BG_IMG_RECOLOR = 42, + LV_STYLE_BG_IMG_RECOLOR_OPA = 43, + LV_STYLE_BG_IMG_TILED = 44, /*Group 3*/ - LV_STYLE_BORDER_COLOR = 48, - LV_STYLE_BORDER_COLOR_FILTERED = 48 | LV_STYLE_PROP_FILTER, - LV_STYLE_BORDER_OPA = 49, - LV_STYLE_BORDER_WIDTH = 50 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_BORDER_SIDE = 51, - LV_STYLE_BORDER_POST = 52, - - LV_STYLE_OUTLINE_WIDTH = 58 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_OUTLINE_COLOR = 59, - LV_STYLE_OUTLINE_COLOR_FILTERED = 59 | LV_STYLE_PROP_FILTER, - LV_STYLE_OUTLINE_OPA = 60 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_OUTLINE_PAD = 61 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_BORDER_COLOR = 48, + LV_STYLE_BORDER_OPA = 49, + LV_STYLE_BORDER_WIDTH = 50, + LV_STYLE_BORDER_SIDE = 51, + LV_STYLE_BORDER_POST = 52, + LV_STYLE_OUTLINE_WIDTH = 53, + LV_STYLE_OUTLINE_COLOR = 54, + LV_STYLE_OUTLINE_OPA = 55, + LV_STYLE_OUTLINE_PAD = 56, /*Group 4*/ - LV_STYLE_SHADOW_WIDTH = 64 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_SHADOW_OFS_X = 65 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_SHADOW_OFS_Y = 66 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_SHADOW_SPREAD = 67 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_SHADOW_COLOR = 68, - LV_STYLE_SHADOW_COLOR_FILTERED = 68 | LV_STYLE_PROP_FILTER, - LV_STYLE_SHADOW_OPA = 69 | LV_STYLE_PROP_EXT_DRAW, - - LV_STYLE_IMG_OPA = 70, - LV_STYLE_IMG_RECOLOR = 71, - LV_STYLE_IMG_RECOLOR_FILTERED = 71 | LV_STYLE_PROP_FILTER, - LV_STYLE_IMG_RECOLOR_OPA = 72, - - LV_STYLE_LINE_WIDTH = 73 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_LINE_DASH_WIDTH = 74, - LV_STYLE_LINE_DASH_GAP = 75, - LV_STYLE_LINE_ROUNDED = 76, - LV_STYLE_LINE_COLOR = 77, - LV_STYLE_LINE_COLOR_FILTERED = 77 | LV_STYLE_PROP_FILTER, - LV_STYLE_LINE_OPA = 78, + LV_STYLE_SHADOW_WIDTH = 64, + LV_STYLE_SHADOW_OFS_X = 65, + LV_STYLE_SHADOW_OFS_Y = 66, + LV_STYLE_SHADOW_SPREAD = 67, + LV_STYLE_SHADOW_COLOR = 68, + LV_STYLE_SHADOW_OPA = 69, + LV_STYLE_IMG_OPA = 70, + LV_STYLE_IMG_RECOLOR = 71, + LV_STYLE_IMG_RECOLOR_OPA = 72, + LV_STYLE_LINE_WIDTH = 73, + LV_STYLE_LINE_DASH_WIDTH = 74, + LV_STYLE_LINE_DASH_GAP = 75, + LV_STYLE_LINE_ROUNDED = 76, + LV_STYLE_LINE_COLOR = 77, + LV_STYLE_LINE_OPA = 78, /*Group 5*/ - LV_STYLE_ARC_WIDTH = 80 | LV_STYLE_PROP_EXT_DRAW, - LV_STYLE_ARC_ROUNDED = 81, - LV_STYLE_ARC_COLOR = 82, - LV_STYLE_ARC_COLOR_FILTERED = 82 | LV_STYLE_PROP_FILTER, - LV_STYLE_ARC_OPA = 83, - LV_STYLE_ARC_IMG_SRC = 84, - - LV_STYLE_TEXT_COLOR = 87 | LV_STYLE_PROP_INHERIT, - LV_STYLE_TEXT_COLOR_FILTERED = 87 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_FILTER, - LV_STYLE_TEXT_OPA = 88 | LV_STYLE_PROP_INHERIT, - LV_STYLE_TEXT_FONT = 89 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_TEXT_LETTER_SPACE = 90 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_TEXT_LINE_SPACE = 91 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_TEXT_DECOR = 92 | LV_STYLE_PROP_INHERIT, - LV_STYLE_TEXT_ALIGN = 93 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_ARC_WIDTH = 80, + LV_STYLE_ARC_ROUNDED = 81, + LV_STYLE_ARC_COLOR = 82, + LV_STYLE_ARC_OPA = 83, + LV_STYLE_ARC_IMG_SRC = 84, + LV_STYLE_TEXT_COLOR = 85, + LV_STYLE_TEXT_OPA = 86, + LV_STYLE_TEXT_FONT = 87, + LV_STYLE_TEXT_LETTER_SPACE = 88, + LV_STYLE_TEXT_LINE_SPACE = 89, + LV_STYLE_TEXT_DECOR = 90, + LV_STYLE_TEXT_ALIGN = 91, /*Group 6*/ - LV_STYLE_RADIUS = 96, - LV_STYLE_CLIP_CORNER = 97, - LV_STYLE_OPA = 98 | LV_STYLE_PROP_INHERIT, - LV_STYLE_COLOR_FILTER_DSC = 99, - LV_STYLE_COLOR_FILTER_OPA = 100, - LV_STYLE_ANIM_TIME = 101, - LV_STYLE_ANIM_SPEED = 102, - LV_STYLE_TRANSITION = 103, - LV_STYLE_BLEND_MODE = 104, - LV_STYLE_LAYOUT = 105 | LV_STYLE_PROP_LAYOUT_REFR, - LV_STYLE_BASE_DIR = 106 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_OPA = 96, + LV_STYLE_COLOR_FILTER_DSC = 97, + LV_STYLE_COLOR_FILTER_OPA = 98, + LV_STYLE_ANIM = 99, + LV_STYLE_ANIM_TIME = 100, + LV_STYLE_ANIM_SPEED = 101, + LV_STYLE_TRANSITION = 102, + LV_STYLE_BLEND_MODE = 103, + LV_STYLE_TRANSFORM_WIDTH = 104, + LV_STYLE_TRANSFORM_HEIGHT = 105, + LV_STYLE_TRANSLATE_X = 106, + LV_STYLE_TRANSLATE_Y = 107, + LV_STYLE_TRANSFORM_ZOOM = 108, + LV_STYLE_TRANSFORM_ANGLE = 109, + LV_STYLE_TRANSFORM_PIVOT_X = 110, + LV_STYLE_TRANSFORM_PIVOT_Y = 111, _LV_STYLE_LAST_BUILT_IN_PROP = 111, + _LV_STYLE_NUM_BUILT_IN_PROPS = _LV_STYLE_LAST_BUILT_IN_PROP + 1, - LV_STYLE_PROP_ANY = 0xFFFF + LV_STYLE_PROP_ANY = 0xFFFF, + _LV_STYLE_PROP_CONST = 0xFFFF /* magic value for const styles */ } lv_style_prop_t; +enum { + LV_STYLE_RES_NOT_FOUND, + LV_STYLE_RES_FOUND, + LV_STYLE_RES_INHERIT +}; + +typedef uint8_t lv_style_res_t; + /** * Descriptor for style transitions */ @@ -311,8 +319,7 @@ typedef struct { const lv_style_const_prop_t * const_props; } v_p; - uint16_t prop1 : 15; - uint16_t is_const : 1; + uint16_t prop1; uint8_t has_group; uint8_t prop_cnt; } lv_style_t; @@ -339,7 +346,7 @@ void lv_style_reset(lv_style_t * style); /** * Register a new style property for custom usage - * @return a new property ID. + * @return a new property ID, or LV_STYLE_PROP_INV if there are no more available. * @example * lv_style_prop_t MY_PROP; * static inline void lv_style_set_my_prop(lv_style_t * style, lv_color_t value) { @@ -350,7 +357,12 @@ void lv_style_reset(lv_style_t * style); * ... * lv_style_set_my_prop(&style1, lv_palette_main(LV_PALETTE_RED)); */ -lv_style_prop_t lv_style_register_prop(void); +lv_style_prop_t lv_style_register_prop(uint8_t flag); + +/** + * Get the number of custom properties that have been registered thus far. + */ +lv_style_prop_t lv_style_get_num_custom_props(void); /** * Remove a property from a style @@ -371,16 +383,13 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop); void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value); /** - * Get the value of a property - * @param style pointer to a style - * @param prop the ID of a property - * @param value pointer to a `lv_style_value_t` variable to store the value - * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) - * LV_RES_OK: the property was fond, and `value` is set accordingly - * @note For performance reasons there are no sanity check on `style` + * Set a special meta state for a property in a style. + * This function shouldn't be used directly by the user. + * @param style pointer to style + * @param prop the ID of a property (e.g. `LV_STYLE_BG_COLOR`) + * @param meta the meta value to attach to the property in the style */ -lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value); - +void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta); /** * Get the value of a property @@ -390,42 +399,8 @@ lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_st * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) * LV_RES_OK: the property was fond, and `value` is set accordingly * @note For performance reasons there are no sanity check on `style` - * @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places */ -static inline lv_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, - lv_style_value_t * value) -{ - if(style->is_const) { - const lv_style_const_prop_t * const_prop; - for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) { - if(const_prop->prop == prop) { - *value = const_prop->value; - return LV_RES_OK; - } - } - return LV_RES_INV; - } - - if(style->prop_cnt == 0) return LV_RES_INV; - - if(style->prop_cnt > 1) { - uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - uint32_t i; - for(i = 0; i < style->prop_cnt; i++) { - if(props[i] == prop) { - lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; - *value = values[i]; - return LV_RES_OK; - } - } - } - else if(style->prop1 == prop) { - *value = style->v_p.value1; - return LV_RES_OK; - } - return LV_RES_INV; -} +lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value); /** * Initialize a transition descriptor. @@ -450,6 +425,64 @@ void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style */ lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop); +/** + * Get the value of a property + * @param style pointer to a style + * @param prop the ID of a property + * @param value pointer to a `lv_style_value_t` variable to store the value + * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) + * LV_RES_OK: the property was fond, and `value` is set accordingly + * @note For performance reasons there are no sanity check on `style` + * @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places + */ +static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, + lv_style_value_t * value) +{ + if(style->prop1 == LV_STYLE_PROP_ANY) { + const lv_style_const_prop_t * const_prop; + for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) { + lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(const_prop->prop); + if(prop_id == prop) { + if(const_prop->prop & LV_STYLE_PROP_META_INHERIT) + return LV_STYLE_RES_INHERIT; + *value = (const_prop->prop & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(prop_id) : const_prop->value; + return LV_STYLE_RES_FOUND; + } + } + return LV_STYLE_RES_NOT_FOUND; + } + + if(style->prop_cnt == 0) return LV_STYLE_RES_NOT_FOUND; + + if(style->prop_cnt > 1) { + uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint16_t * props = (uint16_t *)tmp; + uint32_t i; + for(i = 0; i < style->prop_cnt; i++) { + lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(props[i]); + if(prop_id == prop) { + if(props[i] & LV_STYLE_PROP_META_INHERIT) + return LV_STYLE_RES_INHERIT; + if(props[i] & LV_STYLE_PROP_META_INITIAL) + *value = lv_style_prop_get_default(prop_id); + else { + lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; + *value = values[i]; + } + return LV_STYLE_RES_FOUND; + } + } + } + else if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) { + if(style->prop1 & LV_STYLE_PROP_META_INHERIT) + return LV_STYLE_RES_INHERIT; + *value = (style->prop1 & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(LV_STYLE_PROP_ID_MASK( + style->prop1)) : style->v_p.value1; + return LV_STYLE_RES_FOUND; + } + return LV_STYLE_RES_NOT_FOUND; +} + /** * Checks if a style is empty (has no properties) * @param style pointer to a style @@ -465,6 +498,14 @@ bool lv_style_is_empty(const lv_style_t * style); */ uint8_t _lv_style_get_prop_group(lv_style_prop_t prop); +/** + * Get the flags of a built-in or custom property. + * + * @param prop a style property + * @return the flags of the property + */ +uint8_t _lv_style_prop_lookup_flags(lv_style_prop_t prop); + #include "lv_style_gen.h" static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) @@ -499,6 +540,20 @@ static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) lv_style_set_pad_column(style, value); } +/** + * @brief Check if the style property has a specified behavioral flag. + * + * Do not pass multiple flags to this function as backwards-compatibility is not guaranteed + * for that. + * + * @param prop Property ID + * @param flag Flag + * @return true if the flag is set for this property + */ +static inline bool lv_style_prop_has_flag(lv_style_prop_t prop, uint8_t flag) +{ + return _lv_style_prop_lookup_flags(prop) & flag; +} /************************* * GLOBAL VARIABLES diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c index b806a996b..13d85607a 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c @@ -120,6 +120,22 @@ void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSFORM_ANGLE, v); } +void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_TRANSFORM_PIVOT_X, v); +} + +void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_TRANSFORM_PIVOT_Y, v); +} + void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value) { lv_style_value_t v = { @@ -176,14 +192,6 @@ void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BG_COLOR, v); } -void lv_style_set_bg_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_BG_COLOR_FILTERED, v); -} - void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -200,14 +208,6 @@ void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BG_GRAD_COLOR, v); } -void lv_style_set_bg_grad_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_BG_GRAD_COLOR_FILTERED, v); -} - void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) { lv_style_value_t v = { @@ -272,14 +272,6 @@ void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BG_IMG_RECOLOR, v); } -void lv_style_set_bg_img_recolor_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_RECOLOR_FILTERED, v); -} - void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -304,14 +296,6 @@ void lv_style_set_border_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BORDER_COLOR, v); } -void lv_style_set_border_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_BORDER_COLOR_FILTERED, v); -} - void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -360,14 +344,6 @@ void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_OUTLINE_COLOR, v); } -void lv_style_set_outline_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_OUTLINE_COLOR_FILTERED, v); -} - void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -424,14 +400,6 @@ void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_SHADOW_COLOR, v); } -void lv_style_set_shadow_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_SHADOW_COLOR_FILTERED, v); -} - void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -456,14 +424,6 @@ void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_IMG_RECOLOR, v); } -void lv_style_set_img_recolor_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_IMG_RECOLOR_FILTERED, v); -} - void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -512,14 +472,6 @@ void lv_style_set_line_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_LINE_COLOR, v); } -void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_LINE_COLOR_FILTERED, v); -} - void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -552,14 +504,6 @@ void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_ARC_COLOR, v); } -void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_ARC_COLOR_FILTERED, v); -} - void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -584,14 +528,6 @@ void lv_style_set_text_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_TEXT_COLOR, v); } -void lv_style_set_text_color_filtered(lv_style_t * style, lv_color_t value) -{ - lv_style_value_t v = { - .color = value - }; - lv_style_set_prop(style, LV_STYLE_TEXT_COLOR_FILTERED, v); -} - void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -680,6 +616,14 @@ void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_COLOR_FILTER_OPA, v); } +void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_style_set_prop(style, LV_STYLE_ANIM, v); +} + void lv_style_set_anim_time(lv_style_t * style, uint32_t value) { lv_style_value_t v = { diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h index 04e1f1a52..8bf3b68f4 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h @@ -13,6 +13,8 @@ void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value); void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value); void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value); void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value); +void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value); +void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value); void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value); void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value); void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value); @@ -20,10 +22,8 @@ void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value); void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value); void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value); void lv_style_set_bg_color(lv_style_t * style, lv_color_t value); -void lv_style_set_bg_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value); -void lv_style_set_bg_grad_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value); void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value); void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value); @@ -32,18 +32,15 @@ void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value); void lv_style_set_bg_img_src(lv_style_t * style, const void * value); void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value); -void lv_style_set_bg_img_recolor_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_bg_img_tiled(lv_style_t * style, bool value); void lv_style_set_border_color(lv_style_t * style, lv_color_t value); -void lv_style_set_border_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_border_width(lv_style_t * style, lv_coord_t value); void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value); void lv_style_set_border_post(lv_style_t * style, bool value); void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value); void lv_style_set_outline_color(lv_style_t * style, lv_color_t value); -void lv_style_set_outline_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value); void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value); @@ -51,27 +48,22 @@ void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value); void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value); void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value); void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value); -void lv_style_set_shadow_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value); -void lv_style_set_img_recolor_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_line_width(lv_style_t * style, lv_coord_t value); void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value); void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value); void lv_style_set_line_rounded(lv_style_t * style, bool value); void lv_style_set_line_color(lv_style_t * style, lv_color_t value); -void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value); void lv_style_set_arc_rounded(lv_style_t * style, bool value); void lv_style_set_arc_color(lv_style_t * style, lv_color_t value); -void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_arc_img_src(lv_style_t * style, const void * value); void lv_style_set_text_color(lv_style_t * style, lv_color_t value); -void lv_style_set_text_color_filtered(lv_style_t * style, lv_color_t value); void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value); void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value); @@ -83,6 +75,7 @@ void lv_style_set_clip_corner(lv_style_t * style, bool value); void lv_style_set_opa(lv_style_t * style, lv_opa_t value); void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value); void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value); void lv_style_set_anim_time(lv_style_t * style, uint32_t value); void lv_style_set_anim_speed(lv_style_t * style, uint32_t value); void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value); @@ -165,6 +158,16 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_TRANSFORM_ANGLE, .value = { .num = (int32_t)val } \ } +#define LV_STYLE_CONST_TRANSFORM_PIVOT_X(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_PIVOT_X, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_PIVOT_Y(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_PIVOT_Y, .value = { .num = (int32_t)val } \ + } + #define LV_STYLE_CONST_PAD_TOP(val) \ { \ .prop = LV_STYLE_PAD_TOP, .value = { .num = (int32_t)val } \ @@ -200,11 +203,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_BG_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_BG_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_BG_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_BG_OPA(val) \ { \ .prop = LV_STYLE_BG_OPA, .value = { .num = (int32_t)val } \ @@ -215,11 +213,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_BG_GRAD_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_BG_GRAD_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_BG_GRAD_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_BG_GRAD_DIR(val) \ { \ .prop = LV_STYLE_BG_GRAD_DIR, .value = { .num = (int32_t)val } \ @@ -260,11 +253,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_BG_IMG_RECOLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_BG_IMG_RECOLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_BG_IMG_RECOLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_BG_IMG_RECOLOR_OPA(val) \ { \ .prop = LV_STYLE_BG_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ @@ -280,11 +268,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_BORDER_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_BORDER_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_BORDER_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_BORDER_OPA(val) \ { \ .prop = LV_STYLE_BORDER_OPA, .value = { .num = (int32_t)val } \ @@ -315,11 +298,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_OUTLINE_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_OUTLINE_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_OUTLINE_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_OUTLINE_OPA(val) \ { \ .prop = LV_STYLE_OUTLINE_OPA, .value = { .num = (int32_t)val } \ @@ -355,11 +333,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_SHADOW_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_SHADOW_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_SHADOW_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_SHADOW_OPA(val) \ { \ .prop = LV_STYLE_SHADOW_OPA, .value = { .num = (int32_t)val } \ @@ -375,11 +348,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_IMG_RECOLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_IMG_RECOLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_IMG_RECOLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_IMG_RECOLOR_OPA(val) \ { \ .prop = LV_STYLE_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ @@ -410,11 +378,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_LINE_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_LINE_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_LINE_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_LINE_OPA(val) \ { \ .prop = LV_STYLE_LINE_OPA, .value = { .num = (int32_t)val } \ @@ -435,11 +398,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_ARC_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_ARC_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_ARC_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_ARC_OPA(val) \ { \ .prop = LV_STYLE_ARC_OPA, .value = { .num = (int32_t)val } \ @@ -455,11 +413,6 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_TEXT_COLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_TEXT_COLOR_FILTERED(val) \ - { \ - .prop = LV_STYLE_TEXT_COLOR_FILTERED, .value = { .color = val } \ - } - #define LV_STYLE_CONST_TEXT_OPA(val) \ { \ .prop = LV_STYLE_TEXT_OPA, .value = { .num = (int32_t)val } \ @@ -515,6 +468,11 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); .prop = LV_STYLE_COLOR_FILTER_OPA, .value = { .num = (int32_t)val } \ } +#define LV_STYLE_CONST_ANIM(val) \ + { \ + .prop = LV_STYLE_ANIM, .value = { .ptr = val } \ + } + #define LV_STYLE_CONST_ANIM_TIME(val) \ { \ .prop = LV_STYLE_ANIM_TIME, .value = { .num = (int32_t)val } \ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h index ce94c7b04..a9a8e50de 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h @@ -13,6 +13,7 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" +#include "../hal/lv_hal_tick.h" #include #include @@ -68,6 +69,24 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void); //! @endcond +/** + * Call it in the super-loop of main() or threads. It will run lv_timer_handler() + * with a given period in ms. You can use it with sleep or delay in OS environment. + * This function is used to simplify the porting. + * @param __ms the period for running lv_timer_handler() + */ +static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler_run_in_period(uint32_t ms) +{ + static uint32_t last_tick = 0; + uint32_t curr_tick = lv_tick_get(); + + if((curr_tick - last_tick) >= (ms)) { + last_tick = curr_tick; + return lv_timer_handler(); + } + return 1; +} + /** * Create an "empty" timer. It needs to initialized with at least * `lv_timer_set_cb` and `lv_timer_set_period` diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c index 64197f977..27e0a46cf 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c @@ -1157,18 +1157,22 @@ void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t size) return block_prepare_used(control, block, adjust); } -void lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr) +size_t lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr) { + size_t size = 0; /* Don't attempt to free a NULL pointer. */ if(ptr) { control_t * control = tlsf_cast(control_t *, tlsf); block_header_t * block = block_from_ptr(ptr); tlsf_assert(!block_is_free(block) && "block already marked as free"); + size = block->size; block_mark_as_free(block); block = block_merge_prev(control, block); block = block_merge_next(control, block); block_insert(control, block); } + + return size; } /* @@ -1204,6 +1208,10 @@ void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size) const size_t cursize = block_size(block); const size_t combined = cursize + block_size(next) + block_header_overhead; const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + if(size > cursize && adjust == 0) { + /* The request is probably too large, fail */ + return NULL; + } tlsf_assert(!block_is_free(block) && "block already marked as free"); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h index 9380ee8ca..f12590b60 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h @@ -66,7 +66,7 @@ void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool); void * lv_tlsf_malloc(lv_tlsf_t tlsf, size_t bytes); void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t bytes); void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size); -void lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr); +size_t lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr); /* Returns internal block size, not original request size */ size_t lv_tlsf_block_size(void * ptr); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c index 3879b48d9..da7eca0bb 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c @@ -161,9 +161,10 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * @param txt a '\0' terminated string * @param font pointer to a font * @param letter_space letter space - * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks + * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid line breaks * @param flags settings for the text from 'txt_flag_type' enum * @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL. + * @param cmd_state pointer to a txt_cmd_state_t variable which stores the current state of command processing * @param force Force return the fraction of the word that can fit in the provided space. * @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different) */ @@ -519,8 +520,8 @@ static uint8_t lv_txt_utf8_size(const char * str) } /** - * Convert an Unicode letter to UTF-8. - * @param letter_uni an Unicode letter + * Convert a Unicode letter to UTF-8. + * @param letter_uni a Unicode letter * @return UTF-8 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű') */ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni) @@ -546,6 +547,9 @@ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni) bytes[2] = ((letter_uni >> 6) & 0x3F) | 0x80; bytes[3] = ((letter_uni >> 0) & 0x3F) | 0x80; } + else { + return 0; + } uint32_t * res_p = (uint32_t *)bytes; return *res_p; @@ -761,8 +765,8 @@ static uint8_t lv_txt_iso8859_1_size(const char * str) } /** - * Convert an Unicode letter to ISO8859-1. - * @param letter_uni an Unicode letter + * Convert a Unicode letter to ISO8859-1. + * @param letter_uni a Unicode letter * @return ISO8859-1 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű') */ static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni) @@ -794,7 +798,7 @@ static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c) */ static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i) { - if(i == NULL) return txt[1]; /*Get the next char*/ + if(i == NULL) return txt[0]; /*Get the next char*/ uint8_t letter = txt[*i]; (*i)++; diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h index 4f134ab6d..46050dc3c 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h @@ -77,7 +77,7 @@ typedef uint8_t lv_text_align_t; * @param letter_space letter space of the text * @param line_space line space of the text * @param flags settings for the text from ::lv_text_flag_t - * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid + * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid * line breaks */ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, @@ -88,7 +88,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * @param txt a '\0' terminated string * @param font pointer to a font * @param letter_space letter space - * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid + * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid * line breaks * @param used_width When used_width != NULL, save the width of this line if * flag == LV_TEXT_FLAG_NONE, otherwise save -1. @@ -195,8 +195,8 @@ static inline bool _lv_txt_is_break_char(uint32_t letter) extern uint8_t (*_lv_txt_encoded_size)(const char *); /** - * Convert an Unicode letter to encoded - * @param letter_uni an Unicode letter + * Convert a Unicode letter to encoded + * @param letter_uni a Unicode letter * @return Encoded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ü') */ extern uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h index 9f8ef4ca6..84aee1030 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h @@ -77,7 +77,7 @@ typedef uint32_t lv_uintptr_t; #define _LV_CONCAT3(x, y, z) x ## y ## z #define LV_CONCAT3(x, y, z) _LV_CONCAT3(x, y, z) -#if defined(PYCPARSER) +#if defined(PYCPARSER) || defined(__CC_ARM) #define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) #elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4) #define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__((format(gnu_printf, fmtstr, vararg))) diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c index 99ffb1f15..da39fdc65 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c @@ -35,7 +35,8 @@ static void lv_arc_draw(lv_event_t * e); static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e); static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part); static void inv_knob_area(lv_obj_t * obj); -static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); +static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); +static lv_coord_t get_angle(const lv_obj_t * obj); static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); static void value_update(lv_obj_t * arc); @@ -317,6 +318,60 @@ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) return ((lv_arc_t *) obj)->type; } +/*===================== + * Other functions + *====================*/ + + +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(obj_to_align); + + lv_obj_update_layout(obj); + + lv_point_t center; + lv_coord_t arc_r; + get_center(obj, ¢er, &arc_r); + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + lv_coord_t indic_width_half = indic_width / 2; + arc_r -= indic_width_half; + arc_r += r_offset; + + uint16_t angle = get_angle(obj); + lv_coord_t knob_x = (arc_r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; + lv_coord_t knob_y = (arc_r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; + lv_obj_align_to(obj_to_align, obj, LV_ALIGN_CENTER, knob_x, knob_y); +} + +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(obj_to_rotate); + + lv_obj_update_layout(obj); + + lv_point_t center; + lv_coord_t arc_r; + get_center(obj, ¢er, &arc_r); + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + lv_coord_t indic_width_half = indic_width / 2; + arc_r -= indic_width_half; + + arc_r += r_offset; + lv_obj_align_to(obj_to_rotate, obj, LV_ALIGN_CENTER, 0, -arc_r); + + lv_obj_update_layout(obj); + + uint16_t angle = get_angle(obj); + lv_coord_t pivot_x = obj_to_rotate->coords.x1 - center.x; + lv_coord_t pivot_y = obj_to_rotate->coords.y1 - center.y; + lv_obj_set_style_transform_pivot_x(obj_to_rotate, -pivot_x, 0); + lv_obj_set_style_transform_pivot_y(obj_to_rotate, -pivot_y, 0); + lv_obj_set_style_transform_angle(obj_to_rotate, angle * 10 + 900, 0); +} + + /********************** * STATIC FUNCTIONS **********************/ @@ -345,7 +400,7 @@ static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) arc->last_angle = arc->indic_angle_end; lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10); @@ -675,7 +730,7 @@ static void inv_knob_area(lv_obj_t * obj) lv_obj_invalidate_area(obj, &a); } -static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) +static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) { lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); @@ -691,15 +746,9 @@ static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) if(arc_r) *arc_r = r; } -static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) +static lv_coord_t get_angle(const lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - lv_coord_t indic_width_half = indic_width / 2; - r -= indic_width_half; - uint16_t angle = arc->rotation; if(arc->type == LV_ARC_MODE_NORMAL) { angle += arc->indic_angle_end; @@ -712,6 +761,18 @@ static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t if(arc->value < range_midpoint) angle += arc->indic_angle_start; else angle += arc->indic_angle_end; } + + return angle; +} + + +static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) +{ + lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + lv_coord_t indic_width_half = indic_width / 2; + r -= indic_width_half; + + lv_coord_t angle = get_angle(obj); lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; @@ -759,12 +820,13 @@ static void value_update(lv_obj_t * obj) } break; case LV_ARC_MODE_REVERSE: - angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); + angle = lv_map(arc->value, arc->min_value, arc->max_value, bg_end, arc->bg_angle_start); lv_arc_set_angles(obj, angle, arc->bg_angle_end); break; case LV_ARC_MODE_NORMAL: angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); lv_arc_set_angles(obj, arc->bg_angle_start, angle); + break; default: LV_LOG_WARN("Invalid mode: %d", arc->type); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h index 8ec39a4aa..fd53fc15c 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h @@ -85,83 +85,83 @@ lv_obj_t * lv_arc_create(lv_obj_t * parent); /** * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param start the start angle */ -void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start); +void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start); /** * Set the end angle of an arc. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param end the end angle */ -void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end); +void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end); /** * Set the start and end angles - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param start the start angle * @param end the end angle */ -void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end); +void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end); /** * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param start the start angle */ -void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start); +void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start); /** * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param end the end angle */ -void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end); +void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end); /** * Set the start and end angles of the arc background - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param start the start angle * @param end the end angle */ -void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end); +void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end); /** * Set the rotation for the whole arc - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param rotation rotation angle */ -void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation); +void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation); /** * Set the type of arc. - * @param arc pointer to arc object + * @param obj pointer to arc object * @param mode arc's mode */ -void lv_arc_set_mode(lv_obj_t * arc, lv_arc_mode_t type); +void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type); /** * Set a new value on the arc - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param value new value */ -void lv_arc_set_value(lv_obj_t * arc, int16_t value); +void lv_arc_set_value(lv_obj_t * obj, int16_t value); /** * Set minimum and the maximum values of an arc - * @param arc pointer to the arc object + * @param obj pointer to the arc object * @param min minimum value * @param max maximum value */ -void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max); +void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max); /** * Set a change rate to limit the speed how fast the arc should reach the pressed point. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @param rate the change rate */ -void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); +void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate); /*===================== * Getter functions @@ -169,56 +169,56 @@ void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); /** * Get the start angle of an arc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return the start angle [0..360] */ uint16_t lv_arc_get_angle_start(lv_obj_t * obj); /** * Get the end angle of an arc. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return the end angle [0..360] */ uint16_t lv_arc_get_angle_end(lv_obj_t * obj); /** * Get the start angle of an arc background. - * @param arc pointer to an arc object - * @return the start angle [0..360] + * @param obj pointer to an arc object + * @return the start angle [0..360] */ uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj); /** * Get the end angle of an arc background. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return the end angle [0..360] */ uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj); /** * Get the value of an arc - * @param arc pointer to an arc object - * @return the value of the arc + * @param obj pointer to an arc object + * @return the value of the arc */ int16_t lv_arc_get_value(const lv_obj_t * obj); /** * Get the minimum value of an arc - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return the minimum value of the arc */ int16_t lv_arc_get_min_value(const lv_obj_t * obj); /** * Get the maximum value of an arc - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return the maximum value of the arc */ int16_t lv_arc_get_max_value(const lv_obj_t * obj); /** * Get whether the arc is type or not. - * @param arc pointer to an arc object + * @param obj pointer to an arc object * @return arc's mode */ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); @@ -227,6 +227,22 @@ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); * Other functions *====================*/ +/** + * Align an object to the current position of the arc (knob) + * @param obj pointer to an arc object + * @param obj_to_align pointer to an object to align + * @param r_offset consider the radius larger with this value (< 0: for smaller radius) + */ +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset); + +/** + * Rotate an object to the current position of the arc (knob) + * @param obj pointer to an arc object + * @param obj_to_align pointer to an object to rotate + * @param r_offset consider the radius larger with this value (< 0: for smaller radius) + */ +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c index 62f86f794..92a4d2fe3 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c @@ -399,13 +399,10 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_point_t p; if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t * s = lv_event_get_param(e); if(has_popovers_in_top_row(obj)) { /*reserve one row worth of extra space to account for popovers in the top row*/ - *s = btnm->row_cnt > 0 ? lv_obj_get_content_height(obj) / btnm->row_cnt : 0; - } - else { - *s = 0; + lv_coord_t s = btnm->row_cnt > 0 ? lv_obj_get_content_height(obj) / btnm->row_cnt : 0; + lv_event_set_ext_draw_size(e, s); } } if(code == LV_EVENT_STYLE_CHANGED) { diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h index cf586d723..780d57b68 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h @@ -163,7 +163,7 @@ void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width); /** * Make the button matrix like a selector widget (only one button may be checked at a time). * `LV_BTNMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected using - * `lv_btnmatrix_set_ctrl()` or `lv_btnmatrix_set_btn_ctrl_all()`. + * `lv_btnmatrix_set_ctrl()` or `lv_btnmatrix_set_btn_ctrl_all()`. * @param obj pointer to a button matrix object * @param en whether "one check" mode is enabled */ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c index a55429bdf..6b37069ab 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c @@ -76,6 +76,7 @@ void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, lv_coord_t w, lv_coord_t h canvas->dsc.data = buf; lv_img_set_src(obj, &canvas->dsc); + lv_img_cache_invalidate_src(&canvas->dsc); } void lv_canvas_set_px_color(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_color_t c) @@ -157,98 +158,63 @@ void lv_canvas_copy_buf(lv_obj_t * obj, const void * to_copy, lv_coord_t x, lv_c } } -void lv_canvas_transform(lv_obj_t * obj, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, +void lv_canvas_transform(lv_obj_t * obj, lv_img_dsc_t * src_img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y, bool antialias) { #if LV_DRAW_COMPLEX LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(img); + LV_ASSERT_NULL(src_img); lv_canvas_t * canvas = (lv_canvas_t *)obj; - lv_color_t color = lv_obj_get_style_img_recolor(obj, LV_PART_MAIN); - - int32_t dest_width = canvas->dsc.header.w; - int32_t dest_height = canvas->dsc.header.h; + lv_img_dsc_t * dest_img = &canvas->dsc; int32_t x; int32_t y; - bool ret; - lv_img_transform_dsc_t dsc; - dsc.cfg.angle = angle; - dsc.cfg.zoom = zoom; - dsc.cfg.src = img->data; - dsc.cfg.src_w = img->header.w; - dsc.cfg.src_h = img->header.h; - dsc.cfg.cf = img->header.cf; - dsc.cfg.pivot_x = pivot_x; - dsc.cfg.pivot_y = pivot_y; - dsc.cfg.color = color; - dsc.cfg.antialias = antialias; - _lv_img_buf_transform_init(&dsc); + lv_draw_img_dsc_t draw_dsc; + lv_draw_img_dsc_init(&draw_dsc); + draw_dsc.angle = angle; + draw_dsc.zoom = zoom; + draw_dsc.pivot.x = pivot_x; + draw_dsc.pivot.y = pivot_y; + draw_dsc.antialias = antialias; - for(y = -offset_y; y < dest_height - offset_y; y++) { - for(x = -offset_x; x < dest_width - offset_x; x++) { + lv_area_t dest_area; + dest_area.x1 = 0; + dest_area.x2 = dest_img->header.w - 1; + dest_area.y1 = 0; + dest_area.y2 = 0; - ret = _lv_img_buf_transform(&dsc, x, y); + lv_color_t * cbuf = lv_mem_alloc(dest_img->header.w * sizeof(lv_color_t)); + lv_opa_t * abuf = lv_mem_alloc(dest_img->header.w * sizeof(lv_opa_t)); + for(y = 0; y < dest_img->header.h; y++) { + if(y + offset_y >= 0) { + lv_draw_sw_transform(NULL, &dest_area, src_img->data, src_img->header.w, src_img->header.h, src_img->header.w, + &draw_dsc, canvas->dsc.header.cf, cbuf, abuf); - if(ret == false) continue; - - if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) { - /*If the image has no alpha channel just simple set the result color on the canvas*/ - if(lv_img_cf_has_alpha(img->header.cf) == false) { - lv_img_buf_set_px_color(&canvas->dsc, x + offset_x, y + offset_y, dsc.res.color); - } - else { - lv_color_t bg_color = lv_img_buf_get_px_color(&canvas->dsc, x + offset_x, y + offset_y, dsc.cfg.color); - - /*If the canvas has no alpha but the image has mix the image's color with - * canvas*/ - if(lv_img_cf_has_alpha(canvas->dsc.header.cf) == false) { - if(dsc.res.opa < LV_OPA_MAX) dsc.res.color = lv_color_mix(dsc.res.color, bg_color, dsc.res.opa); - lv_img_buf_set_px_color(&canvas->dsc, x + offset_x, y + offset_y, dsc.res.color); - } - /*Both the image and canvas has alpha channel. Some extra calculation is - required*/ - else { - lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&canvas->dsc, x + offset_x, y + offset_y); - /*Pick the foreground if it's fully opaque or the Background is fully - *transparent*/ - if(dsc.res.opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { - lv_img_buf_set_px_color(&canvas->dsc, x + offset_x, y + offset_y, dsc.res.color); - lv_img_buf_set_px_alpha(&canvas->dsc, x + offset_x, y + offset_y, dsc.res.opa); - } - /*Opaque background: use simple mix*/ - else if(bg_opa >= LV_OPA_MAX) { - lv_img_buf_set_px_color(&canvas->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res.color, bg_color, dsc.res.opa)); - } - /*Both colors have alpha. Expensive calculation need to be applied*/ - else { - - /*Info: - * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ - lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res.opa) * (255 - bg_opa)) >> 8); - if(opa_res_2 == 0) { - opa_res_2 = 1; /*never happens, just to be sure*/ - } - lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res.opa * 255) / opa_res_2; - - lv_img_buf_set_px_color(&canvas->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res.color, bg_color, ratio)); - lv_img_buf_set_px_alpha(&canvas->dsc, x + offset_x, y + offset_y, opa_res_2); - } - } + for(x = 0; x < dest_img->header.w; x++) { + if(x + offset_x < 0) continue; + if(x + offset_x >= dest_img->header.w) break; + if(abuf[x]) { + lv_img_buf_set_px_color(dest_img, x + offset_x, y + offset_y, cbuf[x]); + lv_img_buf_set_px_alpha(dest_img, x + offset_x, y + offset_y, abuf[x]); } } + + if(y + offset_y >= dest_img->header.h) break; + dest_area.y1++; + dest_area.y2++; } } + lv_mem_free(cbuf); + lv_mem_free(abuf); lv_obj_invalidate(obj); + #else LV_UNUSED(obj); - LV_UNUSED(img); + LV_UNUSED(src_img); LV_UNUSED(angle); LV_UNUSED(zoom); LV_UNUSED(offset_x); @@ -856,6 +822,9 @@ static void init_fake_disp(lv_obj_t * canvas, lv_disp_t * disp, lv_disp_drv_t * draw_ctx->buf = (void *)dsc->data; lv_disp_drv_use_generic_set_px_cb(disp->driver, dsc->header.cf); + if(LV_COLOR_SCREEN_TRANSP && dsc->header.cf != LV_IMG_CF_TRUE_COLOR_ALPHA) { + drv->screen_transp = 0; + } } static void deinit_fake_disp(lv_obj_t * canvas, lv_disp_t * disp) diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c index e7e650388..241d17776 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c @@ -398,6 +398,26 @@ void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf buf[c] = '\0'; } +int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option) +{ + const char * opts = lv_dropdown_get_options(obj); + uint32_t char_i = 0; + uint32_t opt_i = 0; + const char * start = opts; + + while(start[char_i] != '\0') { + for(char_i = 0; (start[char_i] != '\n') && (start[char_i] != '\0'); char_i++); + + if(memcmp(start, option, LV_MIN(strlen(option), char_i)) == 0) return opt_i; + start = &start[char_i]; + if(start[0] == '\n') start++; + opt_i++; + } + + return -1; +} + + const char * lv_dropdown_get_symbol(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -515,7 +535,7 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) lv_obj_align(label, LV_ALIGN_TOP_RIGHT, 0, 0); break; case LV_TEXT_ALIGN_CENTER: - lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0); break; } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h index 63412f73e..0c55e862c 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h @@ -189,6 +189,14 @@ uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj); */ void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size); +/** + * Get the index of an option. + * @param obj pointer to drop-down object + * @param option an option as string + * @return index of `option` in the list of all options. -1 if not found. + */ +int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option); + /** * Get the symbol on the drop-down list. Typically a down caret or arrow. * @param obj pointer to drop-down list object diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c index 7a1f255e9..f47a789e7 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c @@ -9,6 +9,7 @@ #include "lv_img.h" #if LV_USE_IMG != 0 +#include "../core/lv_disp.h" #include "../misc/lv_assert.h" #include "../draw/lv_img_decoder.h" #include "../misc/lv_fs.h" @@ -134,7 +135,7 @@ void lv_img_set_src(lv_obj_t * obj, const void * src) } if(src_type == LV_IMG_SRC_SYMBOL) { - /*`lv_img_dsc_get_info` couldn't set the with and height of a font so set it here*/ + /*`lv_img_dsc_get_info` couldn't set the width and height of a font so set it here*/ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); @@ -190,16 +191,11 @@ void lv_img_set_angle(lv_obj_t * obj, int16_t angle) lv_img_t * img = (lv_img_t *)obj; if(angle == img->angle) return; - lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; - - lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle + img->angle, transf_zoom, &img->pivot); + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -207,9 +203,15 @@ void lv_img_set_angle(lv_obj_t * obj, int16_t angle) lv_obj_invalidate_area(obj, &a); img->angle = angle; - lv_obj_refresh_ext_draw_size(obj); - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle + img->angle, transf_zoom, &img->pivot); + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_disp_t * disp = lv_obj_get_disp(obj); + lv_disp_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_disp_enable_invalidation(disp, true); + + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -222,17 +224,11 @@ void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_img_t * img = (lv_img_t *)obj; if(img->pivot.x == x && img->pivot.y == y) return; - lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; - - lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - transf_angle += img->angle; - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot); + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -241,9 +237,15 @@ void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) img->pivot.x = x; img->pivot.y = y; - lv_obj_refresh_ext_draw_size(obj); - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot); + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_disp_t * disp = lv_obj_get_disp(obj); + lv_disp_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_disp_enable_invalidation(disp, true); + + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -258,16 +260,11 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) if(zoom == 0) zoom = 1; - lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - - lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - transf_angle += img->angle; - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot); + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom >> 8, &img->pivot); a.x1 += obj->coords.x1 - 1; a.y1 += obj->coords.y1 - 1; a.x2 += obj->coords.x1 + 1; @@ -275,9 +272,15 @@ void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) lv_obj_invalidate_area(obj, &a); img->zoom = zoom; - lv_obj_refresh_ext_draw_size(obj); - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot); + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_disp_t * disp = lv_obj_get_disp(obj); + lv_disp_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_disp_enable_invalidation(disp, true); + + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); a.x1 += obj->coords.x1 - 1; a.y1 += obj->coords.y1 - 1; a.x2 += obj->coords.x1 + 1; @@ -424,14 +427,10 @@ static lv_point_t lv_img_get_transformed_size(lv_obj_t * obj) { lv_img_t * img = (lv_img_t *)obj; - int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - zoom_final = (zoom_final * img->zoom) >> 8; - int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - angle_final += img->angle; lv_area_t area_transform; _lv_img_buf_get_transformed_area(&area_transform, img->w, img->h, - angle_final, zoom_final, &img->pivot); + img->angle, img->zoom, &img->pivot); return (lv_point_t) { lv_area_get_width(&area_transform), lv_area_get_height(&area_transform) @@ -467,42 +466,31 @@ static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_coord_t * s = lv_event_get_param(e); - lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8; - - lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - transf_angle += img->angle; /*If the image has angle provide enough room for the rotated corners*/ - if(transf_angle || transf_zoom != LV_IMG_ZOOM_NONE) { + if(img->angle || img->zoom != LV_IMG_ZOOM_NONE) { lv_area_t a; lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); - _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot); - lv_coord_t pad_ori = *s; - *s = LV_MAX(*s, pad_ori - a.x1); - *s = LV_MAX(*s, pad_ori - a.y1); - *s = LV_MAX(*s, pad_ori + a.x2 - w); - *s = LV_MAX(*s, pad_ori + a.y2 - h); + _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); + *s = LV_MAX(*s, -a.x1); + *s = LV_MAX(*s, -a.y1); + *s = LV_MAX(*s, a.x2 - w); + *s = LV_MAX(*s, a.y2 - h); } } else if(code == LV_EVENT_HIT_TEST) { lv_hit_test_info_t * info = lv_event_get_param(e); - lv_coord_t zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - zoom = (zoom * img->zoom) >> 8; - - lv_coord_t angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - angle += img->angle; /*If the object is exactly image sized (not cropped, not mosaic) and transformed *perform hit test on its transformed area*/ if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) && - (zoom != LV_IMG_ZOOM_NONE || angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { + (img->zoom != LV_IMG_ZOOM_NONE || img->angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t coords; - _lv_img_buf_get_transformed_area(&coords, w, h, angle, zoom, &img->pivot); + _lv_img_buf_get_transformed_area(&coords, w, h, img->angle, img->zoom, &img->pivot); coords.x1 += obj->coords.x1; coords.y1 += obj->coords.y1; coords.x2 += obj->coords.x1; @@ -556,19 +544,13 @@ static void draw_img(lv_event_t * e) return; } - int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - angle_final += img->angle; - - if(angle_final != 0) { + if(img->angle != 0) { info->res = LV_COVER_RES_NOT_COVER; return; } - int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - zoom_final = (zoom_final * img->zoom) >> 8; - const lv_area_t * clip_area = lv_event_get_param(e); - if(zoom_final == LV_IMG_ZOOM_NONE) { + if(img->zoom == LV_IMG_ZOOM_NONE) { if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) { info->res = LV_COVER_RES_NOT_COVER; return; @@ -576,7 +558,7 @@ static void draw_img(lv_event_t * e) } else { lv_area_t a; - _lv_img_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, zoom_final, &img->pivot); + _lv_img_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom, &img->pivot); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -590,12 +572,6 @@ static void draw_img(lv_event_t * e) } else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST) { - int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN); - zoom_final = (zoom_final * img->zoom) >> 8; - - int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN); - angle_final += img->angle; - lv_coord_t obj_w = lv_obj_get_width(obj); lv_coord_t obj_h = lv_obj_get_height(obj); @@ -616,7 +592,7 @@ static void draw_img(lv_event_t * e) } else { _lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h, - angle_final, zoom_final, &bg_pivot); + img->angle, img->zoom, &bg_pivot); /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/ bg_coords.x1 += obj->coords.x1; @@ -636,7 +612,7 @@ static void draw_img(lv_event_t * e) if(code == LV_EVENT_DRAW_MAIN) { if(img->h == 0 || img->w == 0) return; - if(zoom_final == 0) return; + if(img->zoom == 0) return; lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); @@ -666,8 +642,8 @@ static void draw_img(lv_event_t * e) lv_draw_img_dsc_init(&img_dsc); lv_obj_init_draw_img_dsc(obj, LV_PART_MAIN, &img_dsc); - img_dsc.zoom = zoom_final; - img_dsc.angle = angle_final; + img_dsc.zoom = img->zoom; + img_dsc.angle = img->angle; img_dsc.pivot.x = img->pivot.x; img_dsc.pivot.y = img->pivot.y; img_dsc.antialias = img->antialias; diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h index 2a0056431..eb76c8d98 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h @@ -17,6 +17,11 @@ extern "C" { #if LV_USE_IMG != 0 +/*Testing of dependencies*/ +#if LV_USE_LABEL == 0 +#error "lv_img: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#endif + #include "../core/lv_obj.h" #include "../misc/lv_fs.h" #include "../draw/lv_draw.h" @@ -109,6 +114,7 @@ void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y); /** * Set the rotation angle of the image. * The image will be rotated around the set pivot set by `lv_img_set_pivot()` + * Note that indexed and alpha only images can't be transformed. * @param obj pointer to an image object * @param angle rotation angle in degree with 0.1 degree resolution (0..3600: clock wise) */ @@ -116,7 +122,7 @@ void lv_img_set_angle(lv_obj_t * obj, int16_t angle); /** * Set the rotation center of the image. - * The image will be rotated around this point + * The image will be rotated around this point. * @param obj pointer to an image object * @param x rotation center x of the image * @param y rotation center y of the image @@ -126,6 +132,7 @@ void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); /** * Set the zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. * @param img pointer to an image object * @param zoom the zoom factor. * @example 256 or LV_ZOOM_IMG_NONE for no zoom diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c index 0b8a1657a..f4fbe01a5 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c @@ -1,4 +1,4 @@ -/** +/** * @file lv_label.c * */ @@ -1021,6 +1021,7 @@ static void lv_label_refr_text(lv_obj_t * obj) } /*In roll inf. mode keep the size but start offset animations*/ else if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { + const lv_anim_t * anim_template = lv_obj_get_style_anim(obj, LV_PART_MAIN); uint16_t anim_speed = lv_obj_get_style_anim_speed(obj, LV_PART_MAIN); if(anim_speed == 0) anim_speed = LV_LABEL_DEF_SCROLL_SPEED; lv_anim_t a; @@ -1055,8 +1056,14 @@ static void lv_label_refr_text(lv_obj_t * obj) lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_x_anim); int32_t act_time = anim_cur ? anim_cur->act_time : 0; - if(act_time < a.time) { - a.act_time = act_time; /*To keep the old position*/ + + /*If a template animation exists, consider it's start delay and repeat delay*/ + if(anim_template) { + a.act_time = anim_template->act_time; + a.repeat_delay = anim_template->repeat_delay; + } + else if(act_time < a.time) { + a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/ a.early_apply = 0; } @@ -1076,8 +1083,14 @@ static void lv_label_refr_text(lv_obj_t * obj) lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_y_anim); int32_t act_time = anim_cur ? anim_cur->act_time : 0; - if(act_time < a.time) { - a.act_time = act_time; /*To keep the old position*/ + + /*If a template animation exists, consider it's start delay and repeat delay*/ + if(anim_template) { + a.act_time = anim_template->act_time; + a.repeat_delay = anim_template->repeat_delay; + } + else if(act_time < a.time) { + a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/ a.early_apply = 0; } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h index 342e00417..b31a63e59 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h @@ -142,7 +142,7 @@ void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index); /** * Set where text selection should end * @param obj pointer to a label object - * @param index character index where selection should end. `LV_LABEL_TEXT_SELECTION_OFF` for no selection + * @param index character index where selection should end. `LV_LABEL_TEXT_SELECTION_OFF` for no selection */ void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c index 6bb6cd975..df32bd051 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c @@ -83,7 +83,7 @@ void lv_line_set_y_invert(lv_obj_t * obj, bool en) lv_line_t * line = (lv_line_t *)obj; if(line->y_inv == en) return; - line->y_inv = en == false ? 0 : 1; + line->y_inv = en ? 1U : 0U; lv_obj_invalidate(obj); } @@ -98,7 +98,7 @@ bool lv_line_get_y_invert(const lv_obj_t * obj) lv_line_t * line = (lv_line_t *)obj; - return line->y_inv == 0 ? false : true; + return line->y_inv == 1U; } /********************** @@ -143,22 +143,23 @@ static void lv_line_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(code == LV_EVENT_GET_SELF_SIZE) { lv_line_t * line = (lv_line_t *)obj; + if(line->point_num == 0 || line->point_array == NULL) return; + lv_point_t * p = lv_event_get_param(e); lv_coord_t w = 0; lv_coord_t h = 0; - if(line->point_num > 0) { - uint16_t i; - for(i = 0; i < line->point_num; i++) { - w = LV_MAX(line->point_array[i].x, w); - h = LV_MAX(line->point_array[i].y, h); - } - lv_coord_t line_width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); - w += line_width; - h += line_width; - p->x = w; - p->y = h; + uint16_t i; + for(i = 0; i < line->point_num; i++) { + w = LV_MAX(line->point_array[i].x, w); + h = LV_MAX(line->point_array[i].y, h); } + + lv_coord_t line_width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); + w += line_width; + h += line_width; + p->x = w; + p->y = h; } else if(code == LV_EVENT_DRAW_MAIN) { lv_line_t * line = (lv_line_t *)obj; @@ -170,18 +171,17 @@ static void lv_line_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_obj_get_coords(obj, &area); lv_coord_t x_ofs = area.x1 - lv_obj_get_scroll_x(obj); lv_coord_t y_ofs = area.y1 - lv_obj_get_scroll_y(obj); - lv_point_t p1; - lv_point_t p2; lv_coord_t h = lv_obj_get_height(obj); - uint16_t i; lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); /*Read all points and draw the lines*/ + uint16_t i; for(i = 0; i < line->point_num - 1; i++) { - + lv_point_t p1; + lv_point_t p2; p1.x = line->point_array[i].x + x_ofs; p2.x = line->point_array[i + 1].x + x_ofs; diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c index d66f8595f..fd9b3948f 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c @@ -161,17 +161,20 @@ void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t a /*In infinite mode interpret the new ID relative to the currently visible "page"*/ if(roller->mode == LV_ROLLER_MODE_INFINITE) { - int32_t sel_opt_signed = sel_opt; - uint16_t page = roller->sel_opt_id / LV_ROLLER_INF_PAGES; - - /*`sel_opt` should be less than the number of options set by the user. - *If it's more then probably it's a reference from not the first page - *so normalize `sel_opt`*/ - if(page != 0) { - sel_opt_signed -= page * LV_ROLLER_INF_PAGES; + uint32_t real_option_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; + uint16_t current_page = roller->sel_opt_id / real_option_cnt; + /*Set by the user to e.g. 0, 1, 2, 3... + *Upscale the value to the current page*/ + if(sel_opt < real_option_cnt) { + uint16_t act_opt = roller->sel_opt_id - current_page * real_option_cnt; + int32_t sel_opt_signed = sel_opt; + /*Huge jump? Probably from last to first or first to last option.*/ + if(LV_ABS((int16_t)act_opt - sel_opt) > real_option_cnt / 2) { + if(act_opt > sel_opt) sel_opt_signed += real_option_cnt; + else sel_opt_signed -= real_option_cnt; + } + sel_opt = sel_opt_signed + real_option_cnt * current_page; } - - sel_opt = page * LV_ROLLER_INF_PAGES + sel_opt_signed; } roller->sel_opt_id = sel_opt < roller->option_cnt ? sel_opt : roller->option_cnt - 1; diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h index d90001d91..14411dea6 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h @@ -17,6 +17,11 @@ extern "C" { #if LV_USE_ROLLER != 0 +/*Testing of dependencies*/ +#if LV_USE_LABEL == 0 +#error "lv_roller: lv_label is required. Enable it in lv_conf.h (LV_USE_ROLLER 1)" +#endif + #include "../core/lv_obj.h" #include "lv_label.h" diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c index 82f6feea3..faee0faa8 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c @@ -22,7 +22,7 @@ *********************/ #define MY_CLASS &lv_slider_class -#define LV_SLIDER_KNOB_COORD(hor, is_rtl, area) (hor ? (is_rtl ? area.x1 : area.x2) : (is_rtl ? area.y1 : area.y2)) +#define LV_SLIDER_KNOB_COORD(is_rtl, area) (is_rtl ? area.x1 : area.x2) /********************** * TYPEDEFS @@ -33,8 +33,9 @@ **********************/ static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, lv_coord_t knob_size, bool hor); +static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const lv_coord_t knob_size, const bool hor); static void draw_knob(lv_event_t * e); +static bool is_slider_horizontal(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -83,8 +84,8 @@ static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj /*Initialize the allocated 'slider'*/ slider->value_to_set = NULL; - slider->dragging = 0; - slider->left_knob_focus = 0; + slider->dragging = 0U; + slider->left_knob_focus = 0U; lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); @@ -194,40 +195,40 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_point_t p; lv_indev_get_point(indev, &p); - lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - - int32_t range = slider->bar.max_value - slider->bar.min_value; int32_t new_value = 0; - int32_t real_max_value = slider->bar.max_value; - int32_t real_min_value = slider->bar.min_value; - if(w >= h) { - lv_coord_t indic_w = w - bg_left - bg_right; - if(base_dir == LV_BASE_DIR_RTL) { - new_value = (obj->coords.x2 - bg_right) - p.x; /*Make the point relative to the indicator*/ + const int32_t range = slider->bar.max_value - slider->bar.min_value; + if(is_slider_horizontal(obj)) { + const lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + const lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + const lv_coord_t w = lv_obj_get_width(obj); + const lv_coord_t indic_w = w - bg_left - bg_right; + + if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { + /*Make the point relative to the indicator*/ + new_value = (obj->coords.x2 - bg_right) - p.x; } else { - new_value = p.x - (obj->coords.x1 + bg_left); /*Make the point relative to the indicator*/ + /*Make the point relative to the indicator*/ + new_value = p.x - (obj->coords.x1 + bg_left); } new_value = (new_value * range) / indic_w; new_value += slider->bar.min_value; } else { - lv_coord_t indic_h = h - bg_bottom - bg_top; - new_value = p.y - (obj->coords.y2 + bg_bottom); /*Make the point relative to the indicator*/ + const lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + const lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + const lv_coord_t h = lv_obj_get_height(obj); + const lv_coord_t indic_h = h - bg_bottom - bg_top; + + /*Make the point relative to the indicator*/ + new_value = p.y - (obj->coords.y2 + bg_bottom); new_value = (-new_value * range) / indic_h; new_value += slider->bar.min_value; - } + int32_t real_max_value = slider->bar.max_value; + int32_t real_min_value = slider->bar.min_value; /*Figure out the min. and max. for this mode*/ if(slider->value_to_set == &slider->bar.start_value) { real_max_value = slider->bar.cur_value; @@ -236,8 +237,8 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) real_min_value = slider->bar.start_value; } - if(new_value < real_min_value) new_value = real_min_value; - else if(new_value > real_max_value) new_value = real_max_value; + new_value = LV_CLAMP(real_min_value, new_value, real_max_value); + if(*slider->value_to_set != new_value) { *slider->value_to_set = new_value; lv_obj_invalidate(obj); @@ -308,17 +309,17 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) + 1, LV_ANIM_ON); else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) + 1, LV_ANIM_ON); - - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) - 1, LV_ANIM_ON); else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) - 1, LV_ANIM_ON); - - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; } + else { + return; + } + + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return; } else if(code == LV_EVENT_DRAW_MAIN) { draw_knob(e); @@ -330,51 +331,32 @@ static void draw_knob(lv_event_t * e) lv_obj_t * obj = lv_event_get_target(e); lv_slider_t * slider = (lv_slider_t *)obj; lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - lv_coord_t objw = lv_obj_get_width(obj); - lv_coord_t objh = lv_obj_get_height(obj); - bool hor = objw >= objh ? true : false; - lv_coord_t knob_size = hor ? objh : objw; - bool sym = false; - if(slider->bar.mode == LV_BAR_MODE_SYMMETRICAL && slider->bar.min_value < 0 && slider->bar.max_value > 0) sym = true; + const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + const bool is_horizontal = is_slider_horizontal(obj); lv_area_t knob_area; - - /*Horizontal*/ - if(hor) { - if(!sym) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BASE_DIR_RTL, slider->bar.indic_area); - } - else { - if(slider->bar.cur_value >= 0) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BASE_DIR_RTL, slider->bar.indic_area); - } - else { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BASE_DIR_RTL, slider->bar.indic_area); - } - } + lv_coord_t knob_size; + if(is_horizontal) { + knob_size = lv_obj_get_height(obj); + knob_area.x1 = LV_SLIDER_KNOB_COORD(is_rtl, slider->bar.indic_area); } - /*Vertical*/ else { - if(!sym) { - knob_area.y1 = slider->bar.indic_area.y1; - } - else { - if(slider->bar.cur_value >= 0) { - knob_area.y1 = slider->bar.indic_area.y1; - } - else { - knob_area.y1 = slider->bar.indic_area.y2; - } - } + bool is_symmetrical = false; + if(slider->bar.mode == LV_BAR_MODE_SYMMETRICAL && slider->bar.min_value < 0 && + slider->bar.max_value > 0) is_symmetrical = true; + + knob_size = lv_obj_get_width(obj); + if(is_symmetrical && slider->bar.cur_value < 0) knob_area.y1 = slider->bar.indic_area.y2; + else knob_area.y1 = slider->bar.indic_area.y1; } lv_draw_rect_dsc_t knob_rect_dsc; lv_draw_rect_dsc_init(&knob_rect_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - - position_knob(obj, &knob_area, knob_size, hor); + /* Update knob area with knob style */ + position_knob(obj, &knob_area, knob_size, is_horizontal); + /* Update right knob area with calculated knob area */ lv_area_copy(&slider->right_knob_area, &knob_area); lv_obj_draw_part_dsc_t part_draw_dsc; @@ -395,19 +377,20 @@ static void draw_knob(lv_event_t * e) /*Save the draw part_draw_dsc. because it can be modified in the event*/ lv_draw_rect_dsc_t knob_rect_dsc_tmp; lv_memcpy(&knob_rect_dsc_tmp, &knob_rect_dsc, sizeof(lv_draw_rect_dsc_t)); - + /* Draw the right knob */ lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); lv_draw_rect(draw_ctx, &knob_rect_dsc, &slider->right_knob_area); lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - /*Draw a second knob for the start_value side*/ - if(hor) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BASE_DIR_RTL, slider->bar.indic_area); + /*Calculate the second knob area*/ + if(is_horizontal) { + /*use !is_rtl to get the other knob*/ + knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_rtl, slider->bar.indic_area); } else { knob_area.y1 = slider->bar.indic_area.y2; } - position_knob(obj, &knob_area, knob_size, hor); + position_knob(obj, &knob_area, knob_size, is_horizontal); lv_area_copy(&slider->left_knob_area, &knob_area); lv_memcpy(&knob_rect_dsc, &knob_rect_dsc_tmp, sizeof(lv_draw_rect_dsc_t)); @@ -422,9 +405,8 @@ static void draw_knob(lv_event_t * e) } } -static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, lv_coord_t knob_size, bool hor) +static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const lv_coord_t knob_size, const bool hor) { - if(hor) { knob_area->x1 -= (knob_size >> 1); knob_area->x2 = knob_area->x1 + knob_size - 1; @@ -438,9 +420,9 @@ static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, lv_coord_t knob knob_area->x2 = obj->coords.x2; } - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); lv_coord_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_KNOB); @@ -453,4 +435,9 @@ static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, lv_coord_t knob knob_area->y2 += knob_bottom + transf_h; } +static bool is_slider_horizontal(lv_obj_t * obj) +{ + return lv_obj_get_width(obj) >= lv_obj_get_height(obj); +} + #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c index 1b032156e..5ff65ab23 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c @@ -36,8 +36,17 @@ static void draw_main(lv_event_t * e); static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t line_space, lv_coord_t cell_left, lv_coord_t cell_right, lv_coord_t cell_top, lv_coord_t cell_bottom); -static void refr_size(lv_obj_t * obj, uint32_t strat_row); +static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row); +static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col); static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col); +static size_t get_cell_txt_len(const char * txt); +static void copy_cell_txt(char * dst, const char * txt); +static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t * area); + +static inline bool is_cell_empty(void * cell) +{ + return cell == NULL; +} /********************** * STATIC VARIABLES @@ -90,25 +99,16 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c /*Save the control byte*/ if(table->cell_data[cell]) ctrl = table->cell_data[cell][0]; -#if LV_USE_ARABIC_PERSIAN_CHARS - /*Get the size of the Arabic text and process it*/ - size_t len_ap = _lv_txt_ap_calc_bytes_cnt(txt); - table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], len_ap + 1); + size_t to_allocate = get_cell_txt_len(txt); + + table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], to_allocate); LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; - _lv_txt_ap_proc(txt, &table->cell_data[cell][1]); -#else - table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/ - LV_ASSERT_MALLOC(table->cell_data[cell]); - - strcpy(table->cell_data[cell] + 1, txt); /*+1 to skip the format byte*/ -#endif + copy_cell_txt(table->cell_data[cell], txt); table->cell_data[cell][0] = ctrl; - refr_size(obj, row); - - lv_obj_invalidate(obj); + refr_cell_size(obj, row, col); } void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...) @@ -118,8 +118,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con lv_table_t * table = (lv_table_t *)obj; if(col >= table->col_cnt) { - LV_LOG_WARN("lv_table_set_cell_value: invalid column"); - return; + lv_table_set_col_cnt(obj, col + 1); } /*Auto expand*/ @@ -180,26 +179,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con table->cell_data[cell][0] = ctrl; - /*Refresh the row height*/ - lv_coord_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - lv_coord_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - lv_coord_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - lv_coord_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); - - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); - - lv_coord_t h = get_row_height(obj, row, font, letter_space, line_space, - cell_left, cell_right, cell_top, cell_bottom); - - - lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); - lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); - - table->row_h[row] = LV_CLAMP(minh, h, maxh); - - lv_obj_invalidate(obj); + refr_cell_size(obj, row, col); } void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) @@ -207,6 +187,9 @@ void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; + + if(table->row_cnt == row_cnt) return; + uint16_t old_row_cnt = table->row_cnt; table->row_cnt = row_cnt; @@ -235,7 +218,7 @@ void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) lv_memset_00(&table->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(table->cell_data[0])); } - refr_size(obj, 0) ; + refr_size_form_row(obj, 0); } void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) @@ -243,35 +226,18 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; + + if(table->col_cnt == col_cnt) return; + uint16_t old_col_cnt = table->col_cnt; table->col_cnt = col_cnt; - table->col_w = lv_mem_realloc(table->col_w, col_cnt * sizeof(table->row_h[0])); - LV_ASSERT_MALLOC(table->col_w); - if(table->col_w == NULL) return; - - /*Free the unused cells*/ - if(old_col_cnt > col_cnt) { - uint16_t old_cell_cnt = old_col_cnt * table->row_cnt; - uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; - uint32_t i; - for(i = new_cell_cnt; i < old_cell_cnt; i++) { - lv_mem_free(table->cell_data[i]); - } - } char ** new_cell_data = lv_mem_alloc(table->row_cnt * table->col_cnt * sizeof(char *)); LV_ASSERT_MALLOC(new_cell_data); if(new_cell_data == NULL) return; uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; - lv_memset_00(new_cell_data, new_cell_cnt * sizeof(table->cell_data[0])); - /*Initialize the new fields*/ - if(old_col_cnt < col_cnt) { - uint32_t col; - for(col = old_col_cnt; col < col_cnt; col++) { - table->col_w[col] = LV_DPI_DEF; - } - } + lv_memset_00(new_cell_data, new_cell_cnt * sizeof(table->cell_data[0])); /*The new column(s) messes up the mapping of `cell_data`*/ uint32_t old_col_start; @@ -284,13 +250,31 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) lv_memcpy_small(&new_cell_data[new_col_start], &table->cell_data[old_col_start], sizeof(new_cell_data[0]) * min_col_cnt); + + /*Free the old cells (only if the table becomes smaller)*/ + int32_t i; + for(i = 0; i < (int32_t)old_col_cnt - col_cnt; i++) { + uint32_t idx = old_col_start + min_col_cnt + i; + lv_mem_free(table->cell_data[idx]); + table->cell_data[idx] = NULL; + } } lv_mem_free(table->cell_data); table->cell_data = new_cell_data; + /*Initialize the new column widths if any*/ + table->col_w = lv_mem_realloc(table->col_w, col_cnt * sizeof(table->col_w[0])); + LV_ASSERT_MALLOC(table->col_w); + if(table->col_w == NULL) return; - refr_size(obj, 0) ; + uint32_t col; + for(col = old_col_cnt; col < col_cnt; col++) { + table->col_w[col] = LV_DPI_DEF; + } + + + refr_size_form_row(obj, 0) ; } void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w) @@ -303,7 +287,7 @@ void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w) if(col_id >= table->col_cnt) lv_table_set_col_cnt(obj, col_id + 1); table->col_w[col_id] = w; - refr_size(obj, 0) ; + refr_size_form_row(obj, 0); } void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) @@ -318,7 +302,7 @@ void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table uint32_t cell = row * table->col_cnt + col; - if(table->cell_data[cell] == NULL) { + if(is_cell_empty(table->cell_data[cell])) { table->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; @@ -342,7 +326,7 @@ void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_tab uint32_t cell = row * table->col_cnt + col; - if(table->cell_data[cell] == NULL) { + if(is_cell_empty(table->cell_data[cell])) { table->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; @@ -364,12 +348,12 @@ const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col) lv_table_t * table = (lv_table_t *)obj; if(row >= table->row_cnt || col >= table->col_cnt) { - LV_LOG_WARN("lv_table_set_cell_value: invalid row or column"); + LV_LOG_WARN("invalid row or column"); return ""; } uint32_t cell = row * table->col_cnt + col; - if(table->cell_data[cell] == NULL) return ""; + if(is_cell_empty(table->cell_data[cell])) return ""; return &table->cell_data[cell][1]; /*Skip the format byte*/ } @@ -415,8 +399,8 @@ bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table } uint32_t cell = row * table->col_cnt + col; - if(table->cell_data[cell] == NULL) return false; - else return (table->cell_data[cell][0] & ctrl) == ctrl ? true : false; + if(is_cell_empty(table->cell_data[cell])) return false; + else return (table->cell_data[cell][0] & ctrl) == ctrl; } void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) @@ -482,7 +466,7 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_table_t * table = (lv_table_t *)obj; if(code == LV_EVENT_STYLE_CHANGED) { - refr_size(obj, 0); + refr_size_form_row(obj, 0); } else if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); @@ -599,8 +583,6 @@ static void draw_main(lv_event_t * e) lv_point_t txt_size; lv_area_t cell_area; - lv_area_t txt_area; - lv_text_flag_t txt_flags; lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); @@ -608,11 +590,6 @@ static void draw_main(lv_event_t * e) lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - lv_coord_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - lv_coord_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - lv_coord_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); - lv_state_t state_ori = obj->state; obj->state = LV_STATE_DEFAULT; obj->skip_trans = 1; @@ -634,7 +611,7 @@ static void draw_main(lv_event_t * e) cell_area.y2 = obj->coords.y1 + bg_top - 1 - lv_obj_get_scroll_y(obj) + border_width; lv_coord_t scroll_x = lv_obj_get_scroll_x(obj) ; - bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; + bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL; /*Handle custom drawer*/ lv_obj_draw_part_dsc_t part_draw_dsc; @@ -671,15 +648,16 @@ static void draw_main(lv_event_t * e) uint16_t col_merge = 0; for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { - if(table->cell_data[cell + col_merge]) { - char * next_cell_data = table->cell_data[cell + col_merge]; - if(next_cell_data) ctrl = next_cell_data[0]; - if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) - if(rtl) cell_area.x1 -= table->col_w[col + col_merge + 1]; - else cell_area.x2 += table->col_w[col + col_merge + 1]; - else { - break; - } + char * next_cell_data = table->cell_data[cell + col_merge]; + + if(is_cell_empty(next_cell_data)) break; + + lv_table_cell_ctrl_t merge_ctrl = (lv_table_cell_ctrl_t) next_cell_data[0]; + if(merge_ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) { + lv_coord_t offset = table->col_w[col + col_merge + 1]; + + if(rtl) cell_area.x1 -= offset; + else cell_area.x2 += offset; } else { break; @@ -741,6 +719,13 @@ static void draw_main(lv_event_t * e) lv_draw_rect(draw_ctx, &rect_dsc_act, &cell_area_border); if(table->cell_data[cell]) { + const lv_coord_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const lv_coord_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const lv_coord_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const lv_coord_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + lv_text_flag_t txt_flags = LV_TEXT_FLAG_NONE; + lv_area_t txt_area; + txt_area.x1 = cell_area.x1 + cell_left; txt_area.x2 = cell_area.x2 - cell_right; txt_area.y1 = cell_area.y1 + cell_top; @@ -749,7 +734,6 @@ static void draw_main(lv_event_t * e) /*Align the content to the middle if not cropped*/ bool crop = ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP ? true : false; if(crop) txt_flags = LV_TEXT_FLAG_EXPAND; - else txt_flags = LV_TEXT_FLAG_NONE; lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, label_dsc_def.font, label_dsc_act.letter_space, label_dsc_act.line_space, @@ -781,31 +765,66 @@ static void draw_main(lv_event_t * e) draw_ctx->clip_area = clip_area_ori; } -static void refr_size(lv_obj_t * obj, uint32_t strat_row) +/* Refreshes size of the table starting from @start_row row */ +static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row) { - lv_table_t * table = (lv_table_t *)obj; - - uint32_t i; - - lv_coord_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - lv_coord_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - lv_coord_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - lv_coord_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); - lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); - lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); + const lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); + const lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); - for(i = strat_row; i < table->row_cnt; i++) { - table->row_h[i] = get_row_height(obj, i, font, letter_space, line_space, - cell_left, cell_right, cell_top, cell_bottom); - table->row_h[i] = LV_CLAMP(minh, table->row_h[i], maxh); + lv_table_t * table = (lv_table_t *)obj; + uint32_t i; + for(i = start_row; i < table->row_cnt; i++) { + lv_coord_t calculated_height = get_row_height(obj, i, font, letter_space, line_space, + cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); + table->row_h[i] = LV_CLAMP(minh, calculated_height, maxh); } - lv_obj_refresh_self_size(obj) ; + lv_obj_refresh_self_size(obj); + lv_obj_invalidate(obj); +} + + +static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col) +{ + const lv_coord_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const lv_coord_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + + lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); + lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); + + const lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); + const lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); + + lv_table_t * table = (lv_table_t *)obj; + lv_coord_t calculated_height = get_row_height(obj, row, font, letter_space, line_space, + cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); + + lv_coord_t prev_row_size = table->row_h[row]; + table->row_h[row] = LV_CLAMP(minh, calculated_height, maxh); + + /*If the row height havn't changed invalidate only this cell*/ + if(prev_row_size == table->row_h[row]) { + lv_area_t cell_area; + get_cell_area(obj, row, col, &cell_area); + lv_area_move(&cell_area, obj->coords.x1, obj->coords.y1); + lv_obj_invalidate_area(obj, &cell_area); + } + else { + lv_obj_refresh_self_size(obj); + lv_obj_invalidate(obj); + } } static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_t * font, @@ -813,54 +832,61 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ lv_coord_t cell_left, lv_coord_t cell_right, lv_coord_t cell_top, lv_coord_t cell_bottom) { lv_table_t * table = (lv_table_t *)obj; - lv_point_t txt_size; - lv_coord_t txt_w; + lv_coord_t h_max = lv_font_get_line_height(font) + cell_top + cell_bottom; + /* Calculate the cell_data index where to start */ uint16_t row_start = row_id * table->col_cnt; + + /* Traverse the cells in the row_id row */ uint16_t cell; uint16_t col; - lv_coord_t h_max = lv_font_get_line_height(font) + cell_top + cell_bottom; - for(cell = row_start, col = 0; cell < row_start + table->col_cnt; cell++, col++) { - if(table->cell_data[cell] != NULL) { - txt_w = table->col_w[col]; - uint16_t col_merge = 0; - for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { + char * cell_data = table->cell_data[cell]; - if(table->cell_data[cell + col_merge] != NULL) { - lv_table_cell_ctrl_t ctrl = 0; - char * next_cell_data = table->cell_data[cell + col_merge]; - if(next_cell_data) ctrl = next_cell_data[0]; - if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) - txt_w += table->col_w[col + col_merge + 1]; - else - break; - } - else { - break; - } + if(is_cell_empty(cell_data)) { + continue; + } + + lv_coord_t txt_w = table->col_w[col]; + + /* Traverse the current row from the first until the penultimate column. + * Increment the text width if the cell has the LV_TABLE_CELL_CTRL_MERGE_RIGHT control, + * exit the traversal when the current cell control is not LV_TABLE_CELL_CTRL_MERGE_RIGHT */ + uint16_t col_merge = 0; + for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { + char * next_cell_data = table->cell_data[cell + col_merge]; + + if(is_cell_empty(next_cell_data)) break; + + lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) next_cell_data[0]; + if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) { + txt_w += table->col_w[col + col_merge + 1]; } - - lv_table_cell_ctrl_t ctrl = 0; - if(table->cell_data[cell]) ctrl = table->cell_data[cell][0]; - - /*With text crop assume 1 line*/ - if(ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP) { - h_max = LV_MAX(lv_font_get_line_height(font) + cell_top + cell_bottom, - h_max); - } - /*Without text crop calculate the height of the text in the cell*/ else { - txt_w -= cell_left + cell_right; - - lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, font, - letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); - - h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max); - cell += col_merge; - col += col_merge; + break; } } + + lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) cell_data[0]; + + /*When cropping the text we can assume the row height is equal to the line height*/ + if(ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP) { + h_max = LV_MAX(lv_font_get_line_height(font) + cell_top + cell_bottom, + h_max); + } + /*Else we have to calculate the height of the cell text*/ + else { + lv_point_t txt_size; + txt_w -= cell_left + cell_right; + + lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, font, + letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); + + h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max); + /*Skip until one element after the last merged column*/ + cell += col_merge; + col += col_merge; + } } return h_max; @@ -917,5 +943,65 @@ static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) return LV_RES_OK; } +/* Returns number of bytes to allocate based on chars configuration */ +static size_t get_cell_txt_len(const char * txt) +{ + size_t retval = 0; + +#if LV_USE_ARABIC_PERSIAN_CHARS + retval = _lv_txt_ap_calc_bytes_cnt(txt) + 1; +#else + /* cell_data layout: [ctrl][txt][trailing '\0' terminator] + * +2 because of the trailing '\0' and the ctrl */ + retval = strlen(txt) + 2; +#endif + + return retval; +} + +/* Copy txt into dst skipping the format byte */ +static void copy_cell_txt(char * dst, const char * txt) +{ +#if LV_USE_ARABIC_PERSIAN_CHARS + _lv_txt_ap_proc(txt, &dst[1]); +#else + strcpy(&dst[1], txt); +#endif +} + +static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t * area) +{ + lv_table_t * table = (lv_table_t *)obj; + + uint32_t c; + area->x1 = 0; + for(c = 0; c < col; c++) { + area->x1 += table->col_w[c]; + } + + bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL; + if(rtl) { + area->x1 += lv_obj_get_scroll_x(obj); + lv_coord_t w = lv_obj_get_width(obj); + area->x2 = w - area->x1 - lv_obj_get_style_pad_right(obj, 0); + area->x1 = area->x2 - table->col_w[col]; + } + else { + area->x1 -= lv_obj_get_scroll_x(obj); + area->x1 += lv_obj_get_style_pad_left(obj, 0); + area->x2 = area->x1 + table->col_w[col] - 1; + } + + uint32_t r; + area->y1 = 0; + for(r = 0; r < row; r++) { + area->y1 += table->row_h[r]; + } + + area->y1 += lv_obj_get_style_pad_top(obj, 0); + area->y1 -= lv_obj_get_scroll_y(obj); + area->y2 = area->y1 + table->row_h[row] - 1; + +} #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c index 0dff383d7..4d497e669 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c @@ -34,6 +34,7 @@ #endif #define LV_TEXTAREA_PWD_BULLET_UNICODE 0x2022 +#define IGNORE_KERNING '\0' /********************** * TYPEDEFS @@ -57,6 +58,8 @@ static void update_cursor_position_on_click(lv_event_t * e); static lv_res_t insert_handler(lv_obj_t * obj, const char * txt); static void draw_placeholder(lv_event_t * e); static void draw_cursor(lv_event_t * e); +static void auto_hide_characters(lv_obj_t * obj); +static inline bool is_valid_but_non_printable_char(const uint32_t letter); /********************** * STATIC VARIABLES @@ -100,13 +103,16 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) lv_textarea_t * ta = (lv_textarea_t *)obj; - const char * letter_buf; + if(ta->one_line && (c == '\n' || c == '\r')) { + LV_LOG_INFO("Text area: line break ignored in one-line mode"); + return; + } uint32_t u32_buf[2]; u32_buf[0] = c; u32_buf[1] = 0; - letter_buf = (char *)&u32_buf; + const char * letter_buf = (char *)&u32_buf; #if LV_BIG_ENDIAN_SYSTEM if(c != 0) while(*letter_buf == 0) ++letter_buf; @@ -115,11 +121,6 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) lv_res_t res = insert_handler(obj, letter_buf); if(res != LV_RES_OK) return; - if(ta->one_line && (c == '\n' || c == '\r')) { - LV_LOG_INFO("Text area: line break ignored in one-line mode"); - return; - } - uint32_t c_uni = _lv_txt_encoded_next((const char *)&c, NULL); if(char_is_accepted(obj, c_uni) == false) { @@ -127,7 +128,7 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) return; } - if(ta->pwd_mode != 0) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ + if(ta->pwd_mode) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ /*If the textarea is empty, invalidate it to hide the placeholder*/ if(ta->placeholder_txt) { @@ -136,30 +137,19 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) } lv_label_ins_text(ta->label, ta->cursor.pos, letter_buf); /*Insert the character*/ - lv_textarea_clear_selection(obj); /*Clear selection*/ + lv_textarea_clear_selection(obj); /*Clear selection*/ - if(ta->pwd_mode != 0) { - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + strlen(letter_buf) + 1); /*+2: the new char + \0*/ + if(ta->pwd_mode) { + /*+2: the new char + \0*/ + size_t realloc_size = strlen(ta->pwd_tmp) + strlen(letter_buf) + 1; + ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, (const char *)letter_buf); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } /*Move the cursor after the new character*/ @@ -175,7 +165,7 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) lv_textarea_t * ta = (lv_textarea_t *)obj; - if(ta->pwd_mode != 0) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ + if(ta->pwd_mode) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ /*Add the character one-by-one if not all characters are accepted or there is character limit.*/ if(lv_textarea_get_accepted_chars(obj) || lv_textarea_get_max_length(obj)) { @@ -200,28 +190,16 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) lv_label_ins_text(ta->label, ta->cursor.pos, txt); lv_textarea_clear_selection(obj); - if(ta->pwd_mode != 0) { - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + strlen(txt) + 1); + if(ta->pwd_mode) { + size_t realloc_size = strlen(ta->pwd_tmp) + strlen(txt) + 1; + ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, txt); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } /*Move the cursor after the new text*/ @@ -259,7 +237,7 @@ void lv_textarea_del_char(lv_obj_t * obj) if(txt[0] == '\0') lv_obj_invalidate(obj); } - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { _lv_txt_cut(ta->pwd_tmp, ta->cursor.pos - 1, 1); ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + 1); @@ -301,7 +279,7 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) if(lv_textarea_get_accepted_chars(obj) || lv_textarea_get_max_length(obj)) { lv_label_set_text(ta->label, ""); lv_textarea_set_cursor_pos(obj, LV_TEXTAREA_CURSOR_LAST); - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { ta->pwd_tmp[0] = '\0'; /*Clear the password too*/ } uint32_t i = 0; @@ -321,27 +299,14 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) if(txt_act[0] == '\0') lv_obj_invalidate(obj); } - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(txt) + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; strcpy(ta->pwd_tmp, txt); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); @@ -355,29 +320,22 @@ void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) lv_textarea_t * ta = (lv_textarea_t *)obj; size_t txt_len = strlen(txt); - - if(txt_len == 0) { - if(ta->placeholder_txt) { - lv_mem_free(ta->placeholder_txt); - ta->placeholder_txt = NULL; - } + if((txt_len == 0) && (ta->placeholder_txt)) { + lv_mem_free(ta->placeholder_txt); + ta->placeholder_txt = NULL; } else { - /*Allocate memory for the placeholder_txt text*/ - if(ta->placeholder_txt == NULL) { - ta->placeholder_txt = lv_mem_alloc(txt_len + 1); - } - else { - ta->placeholder_txt = lv_mem_realloc(ta->placeholder_txt, txt_len + 1); - - } + /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ + ta->placeholder_txt = lv_mem_realloc(ta->placeholder_txt, txt_len + 1); LV_ASSERT_MALLOC(ta->placeholder_txt); if(ta->placeholder_txt == NULL) { LV_LOG_ERROR("lv_textarea_set_placeholder_text: couldn't allocate memory for placeholder"); return; } + strcpy(ta->placeholder_txt, txt); + ta->placeholder_txt[txt_len] = '\0'; } lv_obj_invalidate(obj); @@ -440,7 +398,7 @@ void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - ta->cursor.click_pos = en ? 1 : 0; + ta->cursor.click_pos = en ? 1U : 0U; } void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) @@ -450,11 +408,12 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_mode == en) return; - ta->pwd_mode = en == false ? 0 : 1; + ta->pwd_mode = en ? 1U : 0U; /*Pwd mode is now enabled*/ - if(en != false) { - char * txt = lv_label_get_text(ta->label); + if(en) { + char * txt = lv_label_get_text(ta->label); size_t len = strlen(txt); + ta->pwd_tmp = lv_mem_alloc(len + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; @@ -476,6 +435,36 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) refr_cursor_area(obj); } +void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(bullet); + + lv_textarea_t * ta = (lv_textarea_t *)obj; + + if(!bullet && (ta->pwd_bullet)) { + lv_mem_free(ta->pwd_bullet); + ta->pwd_bullet = NULL; + } + else { + size_t txt_len = strlen(bullet); + + /*Allocate memory for the pwd_bullet text*/ + /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ + ta->pwd_bullet = lv_mem_realloc(ta->pwd_bullet, txt_len + 1); + LV_ASSERT_MALLOC(ta->pwd_bullet); + if(ta->pwd_bullet == NULL) { + LV_LOG_ERROR("lv_textarea_set_password_bullet: couldn't allocate memory for bullet"); + return; + } + + strcpy(ta->pwd_bullet, bullet); + ta->pwd_bullet[txt_len] = '\0'; + } + + lv_obj_invalidate(obj); +} + void lv_textarea_set_one_line(lv_obj_t * obj, bool en) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -483,21 +472,21 @@ void lv_textarea_set_one_line(lv_obj_t * obj, bool en) lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->one_line == en) return; - if(en) { - ta->one_line = 1; - lv_obj_set_width(ta->label, LV_SIZE_CONTENT); - lv_obj_set_style_min_width(ta->label, lv_pct(100), 0); + ta->one_line = en ? 1U : 0U; + lv_coord_t width = en ? LV_SIZE_CONTENT : lv_pct(100); + lv_coord_t min_width_value = en ? lv_pct(100) : 0; + lv_obj_set_width(ta->label, width); + lv_obj_set_style_min_width(ta->label, min_width_value, 0); + + if(en) { lv_obj_set_height(obj, LV_SIZE_CONTENT); - lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } else { - ta->one_line = 0; - lv_obj_set_width(ta->label, lv_pct(100)); - lv_obj_set_style_min_width(ta->label, 0, 0); lv_obj_remove_local_style_prop(obj, LV_STYLE_HEIGHT, LV_PART_MAIN); - lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } + + lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list) @@ -628,7 +617,24 @@ bool lv_textarea_get_password_mode(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - return ta->pwd_mode == 0 ? false : true; + return ta->pwd_mode == 1U; +} + +const char * lv_textarea_get_password_bullet(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_textarea_t * ta = (lv_textarea_t *)obj; + + if(ta->pwd_bullet) return ta->pwd_bullet; + + lv_font_glyph_dsc_t g; + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + + /*If the textarea's font has the bullet character use it else fallback to "*"*/ + if(lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0)) + return LV_SYMBOL_BULLET; + return "*"; } bool lv_textarea_get_one_line(const lv_obj_t * obj) @@ -636,7 +642,7 @@ bool lv_textarea_get_one_line(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - return ta->one_line == 0 ? false : true; + return ta->one_line == 1U; } const char * lv_textarea_get_accepted_chars(lv_obj_t * obj) @@ -805,6 +811,7 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * o ta->pwd_mode = 0; ta->pwd_tmp = NULL; + ta->pwd_bullet = NULL; ta->pwd_show_time = LV_TEXTAREA_DEF_PWD_SHOW_TIME; ta->accepted_chars = NULL; ta->max_length = 0; @@ -841,6 +848,10 @@ static void lv_textarea_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_mem_free(ta->pwd_tmp); ta->pwd_tmp = NULL; } + if(ta->pwd_bullet != NULL) { + lv_mem_free(ta->pwd_bullet); + ta->pwd_bullet = NULL; + } if(ta->placeholder_txt != NULL) { lv_mem_free(ta->placeholder_txt); ta->placeholder_txt = NULL; @@ -922,7 +933,7 @@ static void cursor_blink_anim_cb(void * obj, int32_t show) { lv_textarea_t * ta = (lv_textarea_t *)obj; if(show != ta->cursor.show) { - ta->cursor.show = show == 0 ? 0 : 1; + ta->cursor.show = show ? 1U : 0U; lv_area_t area_tmp; lv_area_copy(&area_tmp, &ta->cursor.area); area_tmp.x1 += ta->label->coords.x1; @@ -963,67 +974,56 @@ static void pwd_char_hider_anim_ready(lv_anim_t * a) static void pwd_char_hider(lv_obj_t * obj) { lv_textarea_t * ta = (lv_textarea_t *)obj; - if(ta->pwd_mode != 0) { - char * txt = lv_label_get_text(ta->label); - int32_t enc_len = _lv_txt_get_encoded_length(txt); - if(enc_len == 0) return; - - /*If the textarea's font has "bullet" character use it else fallback to "*"*/ - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_font_glyph_dsc_t g; - bool has_bullet; - has_bullet = lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0); - const char * bullet; - if(has_bullet) bullet = LV_SYMBOL_BULLET; - else bullet = "*"; - - size_t bullet_len = strlen(bullet); - char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); - int32_t i; - for(i = 0; i < enc_len; i++) { - lv_memcpy(&txt_tmp[i * bullet_len], bullet, bullet_len); - } - - txt_tmp[i * bullet_len] = '\0'; - - lv_label_set_text(ta->label, txt_tmp); - lv_mem_buf_release(txt_tmp); - refr_cursor_area(obj); + if(ta->pwd_mode == 0) { + return; } + + /* When ta->label is empty we get 0 back */ + char * txt = lv_label_get_text(ta->label); + uint32_t enc_len = _lv_txt_get_encoded_length(txt); + if(enc_len == 0) return; + + const char * bullet = lv_textarea_get_password_bullet(obj); + const size_t bullet_len = strlen(bullet); + char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); + + uint32_t i; + for(i = 0; i < enc_len; i++) { + lv_memcpy(&txt_tmp[i * bullet_len], bullet, bullet_len); + } + txt_tmp[i * bullet_len] = '\0'; + + lv_label_set_text(ta->label, txt_tmp); + lv_mem_buf_release(txt_tmp); + + refr_cursor_area(obj); } /** - * Test an unicode character if it is accepted or not. Checks max length and accepted char list. + * Test a unicode character if it is accepted or not. Checks max length and accepted char list. * @param ta pointer to a test area object - * @param c an unicode character + * @param c a unicode character * @return true: accepted; false: rejected */ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) { lv_textarea_t * ta = (lv_textarea_t *)obj; - /*If no restriction accept it*/ - if((ta->accepted_chars == NULL || ta->accepted_chars[0] == '\0') && ta->max_length == 0) return true; - /*Too many characters?*/ if(ta->max_length > 0 && _lv_txt_get_encoded_length(lv_textarea_get_text(obj)) >= ta->max_length) { return false; } + if(ta->accepted_chars == NULL || ta->accepted_chars[0] == '\0') return true; /*Accepted character?*/ - if(ta->accepted_chars) { - uint32_t i = 0; + uint32_t i = 0; - while(ta->accepted_chars[i] != '\0') { - uint32_t a = _lv_txt_encoded_next(ta->accepted_chars, &i); - if(a == c) return true; /*Accepted*/ - } + while(ta->accepted_chars[i] != '\0') { + uint32_t a = _lv_txt_encoded_next(ta->accepted_chars, &i); + if(a == c) return true; /*Accepted*/ + } - return false; /*The character wasn't in the list*/ - } - else { - return true; /*If the accepted char list in not specified the accept the character*/ - } + return false; /*The character wasn't in the list*/ } static void start_cursor_blink(lv_obj_t * obj) @@ -1058,22 +1058,17 @@ static void refr_cursor_area(lv_obj_t * obj) uint32_t cur_pos = lv_textarea_get_cursor_pos(obj); const char * txt = lv_label_get_text(ta->label); - uint32_t byte_pos; - byte_pos = _lv_txt_encoded_get_byte_id(txt, cur_pos); - + uint32_t byte_pos = _lv_txt_encoded_get_byte_id(txt, cur_pos); uint32_t letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); - lv_coord_t letter_h = lv_font_get_line_height(font); - + /* Letter height and width */ + const lv_coord_t letter_h = lv_font_get_line_height(font); /*Set letter_w (set not 0 on non printable but valid chars)*/ - lv_coord_t letter_w; - if(letter == '\0' || letter == '\n' || letter == '\r') { - letter_w = lv_font_get_glyph_width(font, ' ', '\0'); - } - else { - /*`letter_next` parameter is '\0' to ignore kerning*/ - letter_w = lv_font_get_glyph_width(font, letter, '\0'); + uint32_t letter_space = letter; + if(is_valid_but_non_printable_char(letter)) { + letter_space = ' '; } + lv_coord_t letter_w = lv_font_get_glyph_width(font, letter_space, IGNORE_KERNING); lv_point_t letter_pos; lv_label_get_letter_pos(ta->label, cur_pos, &letter_pos); @@ -1081,8 +1076,9 @@ static void refr_cursor_area(lv_obj_t * obj) lv_text_align_t align = lv_obj_calculate_style_text_align(ta->label, LV_PART_MAIN, lv_label_get_text(ta->label)); /*If the cursor is out of the text (most right) draw it to the next line*/ - if(letter_pos.x + ta->label->coords.x1 + letter_w > ta->label->coords.x2 && ta->one_line == 0 && - align != LV_TEXT_ALIGN_RIGHT) { + if(((letter_pos.x + ta->label->coords.x1) + letter_w > ta->label->coords.x2) && + (ta->one_line == 0 && align != LV_TEXT_ALIGN_RIGHT)) { + letter_pos.x = 0; letter_pos.y += letter_h + line_space; @@ -1091,12 +1087,11 @@ static void refr_cursor_area(lv_obj_t * obj) letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); } - if(letter == '\0' || letter == '\n' || letter == '\r') { - letter_w = lv_font_get_glyph_width(font, ' ', '\0'); - } - else { - letter_w = lv_font_get_glyph_width(font, letter, '\0'); + uint32_t tmp = letter; + if(is_valid_but_non_printable_char(letter)) { + tmp = ' '; } + letter_w = lv_font_get_glyph_width(font, tmp, IGNORE_KERNING); } /*Save the byte position. It is required to draw `LV_CURSOR_BLOCK`*/ @@ -1139,7 +1134,6 @@ static void update_cursor_position_on_click(lv_event_t * e) lv_indev_t * click_source = lv_indev_get_act(); if(click_source == NULL) return; - lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->cursor.click_pos == 0) return; @@ -1161,26 +1155,27 @@ static void update_cursor_position_on_click(lv_event_t * e) rel_pos.x = point_act.x - label_coords.x1; rel_pos.y = point_act.y - label_coords.y1; - lv_coord_t label_width = lv_obj_get_width(ta->label); + const lv_event_code_t code = lv_event_get_code(e); - uint16_t char_id_at_click; + lv_coord_t label_width = lv_obj_get_width(ta->label); + uint16_t char_id_at_click = 0; #if LV_LABEL_TEXT_SELECTION lv_label_t * label_data = (lv_label_t *)ta->label; - bool click_outside_label; + bool click_outside_label = false; /*Check if the click happened on the left side of the area outside the label*/ if(rel_pos.x < 0) { char_id_at_click = 0; - click_outside_label = true; + click_outside_label = true; } /*Check if the click happened on the right side of the area outside the label*/ else if(rel_pos.x >= label_width) { char_id_at_click = LV_TEXTAREA_CURSOR_LAST; - click_outside_label = true; + click_outside_label = true; } else { char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos); - click_outside_label = !lv_label_is_char_under_pos(ta->label, &rel_pos); + click_outside_label = !lv_label_is_char_under_pos(ta->label, &rel_pos); } if(ta->text_sel_en) { @@ -1250,13 +1245,18 @@ static void update_cursor_position_on_click(lv_event_t * e) #endif } +/* Returns LV_RES_OK when no operation were performed + * Returns LV_RES_INV when a user defined text was inserted */ static lv_res_t insert_handler(lv_obj_t * obj, const char * txt) { ta_insert_replace = NULL; lv_event_send(obj, LV_EVENT_INSERT, (char *)txt); - if(ta_insert_replace) { - if(ta_insert_replace[0] == '\0') return LV_RES_INV; /*Drop this text*/ + /* Drop txt if insert replace is set to '\0' */ + if(ta_insert_replace && ta_insert_replace[0] == '\0') + return LV_RES_INV; + + if(ta_insert_replace) { /*Add the replaced text directly it's different from the original*/ if(strcmp(ta_insert_replace, txt)) { lv_textarea_add_text(obj, ta_insert_replace); @@ -1338,4 +1338,33 @@ static void draw_cursor(lv_event_t * e) } } +static void auto_hide_characters(lv_obj_t * obj) +{ + lv_textarea_t * ta = (lv_textarea_t *) obj; + + if(ta->pwd_show_time == 0) { + pwd_char_hider(obj); + } + else { + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, ta); + lv_anim_set_exec_cb(&a, pwd_char_hider_anim); + lv_anim_set_time(&a, ta->pwd_show_time); + lv_anim_set_values(&a, 0, 1); + lv_anim_set_path_cb(&a, lv_anim_path_step); + lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); + lv_anim_start(&a); + } +} + +static inline bool is_valid_but_non_printable_char(const uint32_t letter) +{ + if(letter == '\0' || letter == '\n' || letter == '\r') { + return true; + } + + return false; +} + #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h index 219e2725e..4b3289b48 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h @@ -42,6 +42,7 @@ typedef struct { lv_obj_t * label; /*Label of the text area*/ char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ char * pwd_tmp; /*Used to store the original text in password mode*/ + char * pwd_bullet; /*Replacement characters displayed in password mode*/ const char * accepted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint32_t max_length; /*The max. number of characters. 0: no limit*/ uint16_t pwd_show_time; /*Time to show characters in password mode before change them to '*'*/ @@ -154,6 +155,13 @@ void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en); */ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en); +/** + * Set the replacement characters to show in password mode + * @param obj pointer to a text area object + * @param bullet pointer to the replacement text + */ +void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet); + /** * Configure the text area to one line or back to normal * @param obj pointer to a text area object @@ -254,6 +262,13 @@ bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj); */ bool lv_textarea_get_password_mode(const lv_obj_t * obj); +/** + * Get the replacement characters to show in password mode + * @param obj pointer to a text area object + * @return pointer to the replacement text + */ +const char * lv_textarea_get_password_bullet(lv_obj_t * obj); + /** * Get the one line configuration attribute * @param obj pointer to a text area object diff --git a/tasmota/lvgl_berry/tasmota_lv_conf.h b/tasmota/lvgl_berry/tasmota_lv_conf.h index 695dd1e0b..bd8464e35 100644 --- a/tasmota/lvgl_berry/tasmota_lv_conf.h +++ b/tasmota/lvgl_berry/tasmota_lv_conf.h @@ -1,6 +1,6 @@ /** * @file lv_conf.h - * Configuration file for v8.2.0 + * Configuration file for v8.3.0 */ /* @@ -29,14 +29,14 @@ /*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ #define LV_COLOR_16_SWAP 1 -/*Enable more complex drawing routines to manage screens transparency. - *Can be used if the UI is above another layer, e.g. an OSD menu or video player. - *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ +/*Enable features to draw on transparent background. + *It's required if opa, and transform_* style properties are used. + *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ #define LV_COLOR_SCREEN_TRANSP 0 /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ -#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) +#define LV_COLOR_MIX_ROUND_OFS 0 /*Images pixels with this color will not be drawn if they are chroma keyed)*/ #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ @@ -55,8 +55,8 @@ #define LV_MEM_ADR 0 /*0: unused*/ /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ #if LV_MEM_ADR == 0 - //#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ - //#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ + #undef LV_MEM_POOL_INCLUDE + #undef LV_MEM_POOL_ALLOC #endif #else /*LV_MEM_CUSTOM*/ @@ -120,6 +120,22 @@ #define LV_CIRCLE_CACHE_SIZE 4 #endif /*LV_DRAW_COMPLEX*/ +/** + * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer + * and blend it as an image with the given opacity. + * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) + * The widget can be buffered in smaller chunks to avoid using large buffers. + * + * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it + * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. + * + * Both buffer sizes are in bytes. + * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers + * and can't be drawn in chunks. So these settings affects only widgets with opacity. + */ +#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) +#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) + /*Default image cache size. Image caching keeps the images opened. *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. @@ -130,24 +146,24 @@ /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ -#define LV_GRADIENT_MAX_STOPS 2 +#define LV_GRADIENT_MAX_STOPS 2 /*Default gradient buffer size. *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. *If the cache is too small the map will be allocated only while it's required for the drawing. *0 mean no caching.*/ -#define LV_GRAD_CACHE_DEF_SIZE 0 +#define LV_GRAD_CACHE_DEF_SIZE 0 /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 1 +#define LV_DITHER_GRADIENT 1 #if LV_DITHER_GRADIENT /*Add support for error diffusion dithering. *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. *The increase in memory consumption is (24 bits * object's width)*/ - #define LV_DITHER_ERROR_DIFFUSION 1 + #define LV_DITHER_ERROR_DIFFUSION 1 #endif /*Maximum buffer size to allocate for rotation. @@ -158,6 +174,9 @@ * GPU *-----------*/ +/*Use Arm's 2D acceleration library Arm-2D */ +#define LV_USE_GPU_ARM2D 0 + /*Use STM32's DMA2D (aka Chrom Art) GPU*/ #define LV_USE_GPU_STM32_DMA2D 0 #if LV_USE_GPU_STM32_DMA2D @@ -166,6 +185,12 @@ #define LV_GPU_DMA2D_CMSIS_INCLUDE #endif +/*Use SWM341's DMA2D GPU*/ +#define LV_USE_GPU_SWM341_DMA2D 0 +#if LV_USE_GPU_SWM341_DMA2D + #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" +#endif + /*Use NXP's PXP GPU iMX RTxxx platforms*/ #define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP @@ -419,6 +444,9 @@ #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ #endif +/*Enable drawing placeholders when glyph dsc is not found*/ +#define LV_USE_FONT_PLACEHOLDER 1 + /*================= * TEXT SETTINGS *=================*/ @@ -473,8 +501,6 @@ #define LV_USE_ARC 1 -#define LV_USE_ANIMIMG 1 - #define LV_USE_BAR 1 #define LV_USE_BTN 1 @@ -520,6 +546,8 @@ /*----------- * Widgets *----------*/ +#define LV_USE_ANIMIMG 1 + #define LV_USE_CALENDAR 0 #if LV_USE_CALENDAR #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 @@ -552,6 +580,12 @@ #define LV_USE_MSGBOX 1 +#define LV_USE_SPAN 1 +#if LV_USE_SPAN + /*A line text can contain maximum num of span descriptor */ + #define LV_SPAN_SNIPPET_STACK_SIZE 64 +#endif + #define LV_USE_SPINBOX 1 #define LV_USE_SPINNER 1 @@ -562,12 +596,6 @@ #define LV_USE_WIN 0 -#define LV_USE_SPAN 1 -#if LV_USE_SPAN - /*A line text can contain maximum num of span descriptor */ - #define LV_SPAN_SNIPPET_STACK_SIZE 64 -#endif - /*----------- * Themes *----------*/ @@ -613,7 +641,7 @@ #if LV_USE_FS_STDIO #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ - #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for open, read, etc*/ @@ -621,19 +649,19 @@ #if LV_USE_FS_POSIX #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ - #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for CreateFile, ReadFile, etc*/ #define LV_USE_FS_WIN32 0 #if LV_USE_FS_WIN32 - #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ -#define LV_USE_FS_FATFS 0 +#define LV_USE_FS_FATFS 0 #if LV_USE_FS_FATFS #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ @@ -677,10 +705,10 @@ /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ -#define LV_USE_FFMPEG 0 +#define LV_USE_FFMPEG 0 #if LV_USE_FFMPEG /*Dump input information to stderr*/ - #define LV_FFMPEG_AV_DUMP_FORMAT 0 + #define LV_FFMPEG_DUMP_FORMAT 0 #endif /*----------- @@ -691,10 +719,37 @@ #define LV_USE_SNAPSHOT 0 /*1: Enable Monkey test*/ -#define LV_USE_MONKEY 0 +#define LV_USE_MONKEY 0 /*1: Enable grid navigation*/ -#define LV_USE_GRIDNAV 0 +#define LV_USE_GRIDNAV 0 + +/*1: Enable lv_obj fragment*/ +#define LV_USE_FRAGMENT 0 + +/*1: Support using images as font in label or span widgets */ +#define LV_USE_IMGFONT 0 + +/*1: Enable a published subscriber based messaging system */ +#define LV_USE_MSG 0 + +/*1: Enable Pinyin input method*/ +/*Requires: lv_keyboard*/ +#define LV_USE_IME_PINYIN 0 +#if LV_USE_IME_PINYIN + /*1: Use default thesaurus*/ + /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ + #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 + /*Set the maximum number of candidate panels that can be displayed*/ + /*This needs to be adjusted according to the size of the screen*/ + #define LV_IME_PINYIN_CAND_TEXT_NUM 6 + + /*Use 9 key input(k9)*/ + #define LV_IME_PINYIN_USE_K9_MODE 1 + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif // LV_IME_PINYIN_USE_K9_MODE +#endif /*================== * EXAMPLES @@ -708,28 +763,32 @@ ====================*/ /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ -#define LV_USE_DEMO_WIDGETS 0 +#define LV_USE_DEMO_WIDGETS 0 #if LV_USE_DEMO_WIDGETS -#define LV_DEMO_WIDGETS_SLIDESHOW 0 +#define LV_DEMO_WIDGETS_SLIDESHOW 0 #endif /*Demonstrate the usage of encoder and keyboard*/ -#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 +#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 /*Benchmark your system*/ -#define LV_USE_DEMO_BENCHMARK 0 +#define LV_USE_DEMO_BENCHMARK 0 +#if LV_USE_DEMO_BENCHMARK +/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ +#define LV_DEMO_BENCHMARK_RGB565A8 0 +#endif /*Stress test for LVGL*/ -#define LV_USE_DEMO_STRESS 0 +#define LV_USE_DEMO_STRESS 0 /*Music player demo*/ -#define LV_USE_DEMO_MUSIC 0 +#define LV_USE_DEMO_MUSIC 0 #if LV_USE_DEMO_MUSIC -# define LV_DEMO_MUSIC_SQUARE 0 -# define LV_DEMO_MUSIC_LANDSCAPE 0 -# define LV_DEMO_MUSIC_ROUND 0 -# define LV_DEMO_MUSIC_LARGE 0 -# define LV_DEMO_MUSIC_AUTO_PLAY 0 + #define LV_DEMO_MUSIC_SQUARE 0 + #define LV_DEMO_MUSIC_LANDSCAPE 0 + #define LV_DEMO_MUSIC_ROUND 0 + #define LV_DEMO_MUSIC_LARGE 0 + #define LV_DEMO_MUSIC_AUTO_PLAY 0 #endif /*--END OF LV_CONF_H--*/