Init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin/
|
||||
obj/
|
||||
39
Makefile
Normal file
39
Makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
.PHONY: all clean build zip
|
||||
|
||||
CC := gcc
|
||||
CFLAGS := -MD -Wall -g -lm -lX11 -I ./inc/
|
||||
TARGETS := pm3-lvgl
|
||||
EXES := $(patsubst %,bin/%,$(TARGETS))
|
||||
SRCS := $(shell find src inc -type f -iname '*.c')
|
||||
OBJS := $(patsubst src/%.c,obj/%.o,$(patsubst inc/%.c,obj/lib/%.o,$(SRCS)))
|
||||
NO_BUILD := $(patsubst %,obj/%.o,$(TARGETS))
|
||||
PROJ := edith_boles_$(notdir $(PWD))
|
||||
|
||||
all: build
|
||||
|
||||
build: $(EXES)
|
||||
|
||||
$(EXES): bin/%: obj/%.o $(filter-out $(NO_BUILD), $(OBJS))
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
obj/%.o: src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
obj/lib/%.o: inc/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -rf bin
|
||||
rm -rf obj
|
||||
rm -rf .artifacts
|
||||
rm -rf $(PROJ).zip
|
||||
|
||||
zip: clean
|
||||
mkdir -p .artifacts/$(PROJ)
|
||||
cp -r * .artifacts/$(PROJ)
|
||||
cd .artifacts && zip -r ../$(PROJ).zip $(PROJ)
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
1526
inc/lv_conf.h
Normal file
1526
inc/lv_conf.h
Normal file
File diff suppressed because it is too large
Load Diff
14
inc/lvgl/lv_version.h
Normal file
14
inc/lvgl/lv_version.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @file lv_version.h
|
||||
* The current version of LVGL
|
||||
*/
|
||||
|
||||
#ifndef LV_VERSION_H
|
||||
#define LV_VERSION_H
|
||||
|
||||
#define LVGL_VERSION_MAJOR 9
|
||||
#define LVGL_VERSION_MINOR 5
|
||||
#define LVGL_VERSION_PATCH 0
|
||||
#define LVGL_VERSION_INFO ""
|
||||
|
||||
#endif /* LV_VERSION_H */
|
||||
220
inc/lvgl/lvgl.h
Normal file
220
inc/lvgl/lvgl.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* @file lvgl.h
|
||||
* Include all LVGL related headers
|
||||
*/
|
||||
|
||||
#ifndef LVGL_H
|
||||
#define LVGL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************
|
||||
* CURRENT VERSION OF LVGL
|
||||
***************************/
|
||||
#include "lv_version.h"
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "src/lv_init.h"
|
||||
|
||||
#include "src/stdlib/lv_mem.h"
|
||||
#include "src/stdlib/lv_string.h"
|
||||
#include "src/stdlib/lv_sprintf.h"
|
||||
|
||||
#include "src/misc/lv_log.h"
|
||||
#include "src/misc/lv_timer.h"
|
||||
#include "src/misc/lv_math.h"
|
||||
#include "src/misc/lv_array.h"
|
||||
#include "src/misc/lv_async.h"
|
||||
#include "src/misc/lv_anim_timeline.h"
|
||||
#include "src/misc/lv_profiler_builtin.h"
|
||||
#include "src/misc/lv_rb.h"
|
||||
#include "src/misc/lv_utils.h"
|
||||
#include "src/misc/lv_iter.h"
|
||||
#include "src/misc/lv_circle_buf.h"
|
||||
#include "src/misc/lv_tree.h"
|
||||
|
||||
#include "src/osal/lv_os.h"
|
||||
|
||||
#include "src/tick/lv_tick.h"
|
||||
|
||||
#include "src/core/lv_obj.h"
|
||||
#include "src/core/lv_group.h"
|
||||
#include "src/core/lv_refr.h"
|
||||
#include "src/core/lv_observer.h"
|
||||
#include "src/indev/lv_indev.h"
|
||||
#include "src/indev/lv_indev_gesture.h"
|
||||
#include "src/indev/lv_gridnav.h"
|
||||
#include "src/display/lv_display.h"
|
||||
|
||||
#include "src/font/lv_font.h"
|
||||
#include "src/font/binfont_loader/lv_binfont_loader.h"
|
||||
#include "src/font/fmt_txt/lv_font_fmt_txt.h"
|
||||
#include "src/font/imgfont/lv_imgfont.h"
|
||||
#include "src/font/font_manager/lv_font_manager.h"
|
||||
|
||||
#include "src/widgets/animimage/lv_animimage.h"
|
||||
#include "src/widgets/arc/lv_arc.h"
|
||||
#include "src/widgets/arclabel/lv_arclabel.h"
|
||||
#include "src/widgets/bar/lv_bar.h"
|
||||
#include "src/widgets/button/lv_button.h"
|
||||
#include "src/widgets/buttonmatrix/lv_buttonmatrix.h"
|
||||
#include "src/widgets/calendar/lv_calendar.h"
|
||||
#include "src/widgets/canvas/lv_canvas.h"
|
||||
#include "src/widgets/chart/lv_chart.h"
|
||||
#include "src/widgets/checkbox/lv_checkbox.h"
|
||||
#include "src/widgets/dropdown/lv_dropdown.h"
|
||||
#include "src/widgets/gif/lv_gif.h"
|
||||
#include "src/widgets/image/lv_image.h"
|
||||
#include "src/widgets/imagebutton/lv_imagebutton.h"
|
||||
#include "src/widgets/keyboard/lv_keyboard.h"
|
||||
#include "src/widgets/label/lv_label.h"
|
||||
#include "src/widgets/led/lv_led.h"
|
||||
#include "src/widgets/line/lv_line.h"
|
||||
#include "src/widgets/list/lv_list.h"
|
||||
#include "src/widgets/lottie/lv_lottie.h"
|
||||
#include "src/widgets/menu/lv_menu.h"
|
||||
#include "src/widgets/msgbox/lv_msgbox.h"
|
||||
#include "src/widgets/roller/lv_roller.h"
|
||||
#include "src/widgets/scale/lv_scale.h"
|
||||
#include "src/widgets/slider/lv_slider.h"
|
||||
#include "src/widgets/span/lv_span.h"
|
||||
#include "src/widgets/spinbox/lv_spinbox.h"
|
||||
#include "src/widgets/spinner/lv_spinner.h"
|
||||
#include "src/widgets/switch/lv_switch.h"
|
||||
#include "src/widgets/table/lv_table.h"
|
||||
#include "src/widgets/tabview/lv_tabview.h"
|
||||
#include "src/widgets/textarea/lv_textarea.h"
|
||||
#include "src/widgets/tileview/lv_tileview.h"
|
||||
#include "src/widgets/win/lv_win.h"
|
||||
#include "src/widgets/3dtexture/lv_3dtexture.h"
|
||||
#include "src/widgets/ime/lv_ime_pinyin.h"
|
||||
|
||||
#include "src/debugging/sysmon/lv_sysmon.h"
|
||||
#include "src/debugging/monkey/lv_monkey.h"
|
||||
#include "src/debugging/test/lv_test.h"
|
||||
|
||||
#include "src/others/fragment/lv_fragment.h"
|
||||
#include "src/others/file_explorer/lv_file_explorer.h"
|
||||
#include "src/others/translation/lv_translation.h"
|
||||
|
||||
#include "src/libs/barcode/lv_barcode.h"
|
||||
#include "src/libs/bin_decoder/lv_bin_decoder.h"
|
||||
#include "src/libs/bmp/lv_bmp.h"
|
||||
#include "src/libs/rle/lv_rle.h"
|
||||
#include "src/libs/fsdrv/lv_fsdrv.h"
|
||||
#include "src/libs/lodepng/lv_lodepng.h"
|
||||
#include "src/libs/libpng/lv_libpng.h"
|
||||
#include "src/libs/libwebp/lv_libwebp.h"
|
||||
#include "src/libs/gltf/gltf_data/lv_gltf_model.h"
|
||||
#include "src/libs/gltf/gltf_view/lv_gltf.h"
|
||||
#include "src/libs/gstreamer/lv_gstreamer.h"
|
||||
#include "src/libs/qrcode/lv_qrcode.h"
|
||||
#include "src/libs/tjpgd/lv_tjpgd.h"
|
||||
#include "src/libs/libjpeg_turbo/lv_libjpeg_turbo.h"
|
||||
#include "src/libs/freetype/lv_freetype.h"
|
||||
#include "src/libs/rlottie/lv_rlottie.h"
|
||||
#include "src/libs/ffmpeg/lv_ffmpeg.h"
|
||||
#include "src/libs/tiny_ttf/lv_tiny_ttf.h"
|
||||
#include "src/libs/svg/lv_svg.h"
|
||||
#include "src/libs/svg/lv_svg_render.h"
|
||||
|
||||
#include "src/layouts/lv_layout.h"
|
||||
|
||||
#include "src/draw/lv_draw_buf.h"
|
||||
#include "src/draw/lv_draw_vector.h"
|
||||
#include "src/draw/sw/lv_draw_sw_utils.h"
|
||||
#include "src/draw/eve/lv_draw_eve_target.h"
|
||||
#include "src/draw/snapshot/lv_snapshot.h"
|
||||
|
||||
#include "src/themes/lv_theme.h"
|
||||
|
||||
#include "src/drivers/lv_drivers.h"
|
||||
|
||||
/* Define LV_DISABLE_API_MAPPING using a compiler option
|
||||
* to make sure your application is not using deprecated names */
|
||||
#ifndef LV_DISABLE_API_MAPPING
|
||||
#include "src/lv_api_map_v8.h"
|
||||
#include "src/lv_api_map_v9_0.h"
|
||||
#include "src/lv_api_map_v9_1.h"
|
||||
#include "src/lv_api_map_v9_2.h"
|
||||
#include "src/lv_api_map_v9_3.h"
|
||||
#include "src/lv_api_map_v9_4.h"
|
||||
#endif /*LV_DISABLE_API_MAPPING*/
|
||||
|
||||
#if LV_USE_PRIVATE_API
|
||||
#include "src/lvgl_private.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/** Gives 1 if the x.y.z version is supported in the current version
|
||||
* Usage:
|
||||
*
|
||||
* - Require v6
|
||||
* #if LV_VERSION_CHECK(6,0,0)
|
||||
* new_func_in_v6();
|
||||
* #endif
|
||||
*
|
||||
*
|
||||
* - Require at least v5.3
|
||||
* #if LV_VERSION_CHECK(5,3,0)
|
||||
* new_feature_from_v5_3();
|
||||
* #endif
|
||||
*
|
||||
*
|
||||
* - Require v5.3.2 bugfixes
|
||||
* #if LV_VERSION_CHECK(5,3,2)
|
||||
* bugfix_in_v5_3_2();
|
||||
* #endif
|
||||
*
|
||||
*/
|
||||
#define LV_VERSION_CHECK(x,y,z) (x == LVGL_VERSION_MAJOR && (y < LVGL_VERSION_MINOR || (y == LVGL_VERSION_MINOR && z <= LVGL_VERSION_PATCH)))
|
||||
|
||||
/**
|
||||
* Wrapper functions for VERSION macros
|
||||
*/
|
||||
|
||||
static inline int lv_version_major(void)
|
||||
{
|
||||
return LVGL_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
static inline int lv_version_minor(void)
|
||||
{
|
||||
return LVGL_VERSION_MINOR;
|
||||
}
|
||||
|
||||
static inline int lv_version_patch(void)
|
||||
{
|
||||
return LVGL_VERSION_PATCH;
|
||||
}
|
||||
|
||||
static inline const char * lv_version_info(void)
|
||||
{
|
||||
return LVGL_VERSION_INFO;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LVGL_H*/
|
||||
132
inc/lvgl/lvgl_private.h
Normal file
132
inc/lvgl/lvgl_private.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file lvgl_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LVGL_PRIVATE_H
|
||||
#define LVGL_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "src/core/lv_global.h"
|
||||
|
||||
#include "src/display/lv_display_private.h"
|
||||
#include "src/indev/lv_indev_private.h"
|
||||
#include "src/misc/lv_text_private.h"
|
||||
#include "src/misc/cache/lv_cache.h"
|
||||
#include "src/misc/cache/lv_cache_entry_private.h"
|
||||
#include "src/misc/cache/lv_cache_private.h"
|
||||
#include "src/layouts/lv_layout_private.h"
|
||||
#include "src/stdlib/lv_mem_private.h"
|
||||
#include "src/others/file_explorer/lv_file_explorer_private.h"
|
||||
#include "src/others/fragment/lv_fragment_private.h"
|
||||
#include "src/others/translation/lv_translation_private.h"
|
||||
#include "src/libs/qrcode/lv_qrcode_private.h"
|
||||
#include "src/libs/barcode/lv_barcode_private.h"
|
||||
#include "src/draw/lv_draw_triangle_private.h"
|
||||
#include "src/draw/lv_draw_private.h"
|
||||
#include "src/draw/lv_draw_rect_private.h"
|
||||
#include "src/draw/lv_draw_image_private.h"
|
||||
#include "src/draw/lv_image_decoder_private.h"
|
||||
#include "src/draw/lv_draw_label_private.h"
|
||||
#include "src/draw/lv_draw_vector_private.h"
|
||||
#include "src/draw/lv_draw_buf_private.h"
|
||||
#include "src/draw/sw/lv_draw_sw_private.h"
|
||||
#include "src/draw/sw/lv_draw_sw_mask_private.h"
|
||||
#include "src/draw/sw/blend/lv_draw_sw_blend_private.h"
|
||||
#include "src/drivers/libinput/lv_xkb_private.h"
|
||||
#include "src/drivers/libinput/lv_libinput_private.h"
|
||||
#include "src/drivers/evdev/lv_evdev_private.h"
|
||||
#include "src/themes/lv_theme_private.h"
|
||||
#include "src/core/lv_refr_private.h"
|
||||
#include "src/core/lv_obj_style_private.h"
|
||||
#include "src/core/lv_obj_private.h"
|
||||
#include "src/core/lv_obj_scroll_private.h"
|
||||
#include "src/core/lv_obj_draw_private.h"
|
||||
#include "src/core/lv_obj_class_private.h"
|
||||
#include "src/core/lv_group_private.h"
|
||||
#include "src/core/lv_obj_event_private.h"
|
||||
#include "src/core/lv_observer_private.h"
|
||||
|
||||
#include "src/debugging/sysmon/lv_sysmon_private.h"
|
||||
#include "src/debugging/monkey/lv_monkey_private.h"
|
||||
|
||||
#include "src/font/fmt_txt/lv_font_fmt_txt_private.h"
|
||||
|
||||
#include "src/misc/lv_timer_private.h"
|
||||
#include "src/misc/lv_area_private.h"
|
||||
#include "src/misc/lv_fs_private.h"
|
||||
#include "src/misc/lv_profiler_builtin_private.h"
|
||||
#include "src/misc/lv_event_private.h"
|
||||
#include "src/misc/lv_bidi_private.h"
|
||||
#include "src/misc/lv_rb_private.h"
|
||||
#include "src/misc/lv_style_private.h"
|
||||
#include "src/misc/lv_color_op_private.h"
|
||||
#include "src/misc/lv_anim_private.h"
|
||||
#include "src/misc/lv_anim_timeline_private.h"
|
||||
|
||||
#include "src/widgets/msgbox/lv_msgbox_private.h"
|
||||
#include "src/widgets/buttonmatrix/lv_buttonmatrix_private.h"
|
||||
#include "src/widgets/slider/lv_slider_private.h"
|
||||
#include "src/widgets/switch/lv_switch_private.h"
|
||||
#include "src/widgets/calendar/lv_calendar_private.h"
|
||||
#include "src/widgets/imagebutton/lv_imagebutton_private.h"
|
||||
#include "src/widgets/bar/lv_bar_private.h"
|
||||
#include "src/widgets/image/lv_image_private.h"
|
||||
#include "src/widgets/textarea/lv_textarea_private.h"
|
||||
#include "src/widgets/table/lv_table_private.h"
|
||||
#include "src/widgets/checkbox/lv_checkbox_private.h"
|
||||
#include "src/widgets/roller/lv_roller_private.h"
|
||||
#include "src/widgets/win/lv_win_private.h"
|
||||
#include "src/widgets/keyboard/lv_keyboard_private.h"
|
||||
#include "src/widgets/line/lv_line_private.h"
|
||||
#include "src/widgets/animimage/lv_animimage_private.h"
|
||||
#include "src/widgets/dropdown/lv_dropdown_private.h"
|
||||
#include "src/widgets/menu/lv_menu_private.h"
|
||||
#include "src/widgets/chart/lv_chart_private.h"
|
||||
#include "src/widgets/button/lv_button_private.h"
|
||||
#include "src/widgets/scale/lv_scale_private.h"
|
||||
#include "src/widgets/led/lv_led_private.h"
|
||||
#include "src/widgets/arc/lv_arc_private.h"
|
||||
#include "src/widgets/tileview/lv_tileview_private.h"
|
||||
#include "src/widgets/spinbox/lv_spinbox_private.h"
|
||||
#include "src/widgets/span/lv_span_private.h"
|
||||
#include "src/widgets/label/lv_label_private.h"
|
||||
#include "src/widgets/canvas/lv_canvas_private.h"
|
||||
#include "src/widgets/tabview/lv_tabview_private.h"
|
||||
#include "src/widgets/3dtexture/lv_3dtexture_private.h"
|
||||
#include "src/widgets/ime/lv_ime_pinyin_private.h"
|
||||
|
||||
#include "src/tick/lv_tick_private.h"
|
||||
#include "src/stdlib/builtin/lv_tlsf_private.h"
|
||||
#include "src/libs/rlottie/lv_rlottie_private.h"
|
||||
#include "src/libs/ffmpeg/lv_ffmpeg_private.h"
|
||||
#include "src/widgets/lottie/lv_lottie_private.h"
|
||||
#include "src/osal/lv_os_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LVGL_PRIVATE_H*/
|
||||
312
inc/lvgl/src/core/lv_global.h
Normal file
312
inc/lvgl/src/core/lv_global.h
Normal file
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
* @file lv_global.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GLOBAL_H
|
||||
#define LV_GLOBAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#if LV_USE_DRAW_SW
|
||||
#include "../draw/sw/lv_draw_sw.h"
|
||||
#endif
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color_op.h"
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../osal/lv_os_private.h"
|
||||
#include "../debugging/sysmon/lv_sysmon.h"
|
||||
#include "../stdlib/builtin/lv_tlsf.h"
|
||||
|
||||
#if LV_USE_FONT_COMPRESSED
|
||||
#include "../font/fmt_txt/lv_font_fmt_txt_private.h"
|
||||
#endif
|
||||
|
||||
#include "../tick/lv_tick.h"
|
||||
#include "../layouts/lv_layout.h"
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
#include "../misc/lv_timer_private.h"
|
||||
#include "../misc/lv_anim_private.h"
|
||||
#include "../tick/lv_tick_private.h"
|
||||
#include "../draw/lv_draw_buf_private.h"
|
||||
#include "../draw/lv_draw_private.h"
|
||||
#include "../draw/sw/lv_draw_sw_private.h"
|
||||
#include "../draw/sw/lv_draw_sw_mask_private.h"
|
||||
#include "../stdlib/builtin/lv_tlsf_private.h"
|
||||
#include "../debugging/sysmon/lv_sysmon_private.h"
|
||||
#include "../debugging/test/lv_test_private.h"
|
||||
#include "../layouts/lv_layout_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ZERO_MEM_SENTINEL 0xa1b2c3d4
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_SPAN != 0
|
||||
struct _snippet_stack;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FREETYPE
|
||||
struct _lv_freetype_context_t;
|
||||
#endif
|
||||
|
||||
#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN
|
||||
struct _lv_profiler_builtin_ctx_t;
|
||||
#endif
|
||||
|
||||
#if LV_USE_NUTTX
|
||||
struct _lv_nuttx_ctx_t;
|
||||
#endif
|
||||
|
||||
typedef struct _lv_global_t {
|
||||
/**
|
||||
* User data for the LVGL library. Move from the bottom of the struct
|
||||
* to avoid breaking the ABI. E.g., if the user data is used by a
|
||||
* closed-source library, this can help to avoid re-compiling the library
|
||||
* when the lvgl-related configs are changed.
|
||||
*/
|
||||
void * user_data;
|
||||
|
||||
bool inited;
|
||||
bool deinit_in_progress; /**< Can be used e.g. in the LV_EVENT_DELETE to deinit the drivers too */
|
||||
|
||||
lv_ll_t disp_ll;
|
||||
lv_display_t * disp_refresh;
|
||||
lv_display_t * disp_default;
|
||||
|
||||
lv_ll_t style_trans_ll;
|
||||
bool style_refresh;
|
||||
uint32_t style_custom_table_size;
|
||||
uint32_t style_last_custom_prop_id;
|
||||
uint8_t * style_custom_prop_flag_lookup_table;
|
||||
|
||||
lv_ll_t group_ll;
|
||||
lv_group_t * group_default;
|
||||
|
||||
lv_ll_t indev_ll;
|
||||
lv_indev_t * indev_active;
|
||||
lv_obj_t * indev_obj_active;
|
||||
|
||||
uint32_t layout_count;
|
||||
lv_layout_dsc_t * layout_list;
|
||||
bool layout_update_mutex;
|
||||
|
||||
uint32_t memory_zero;
|
||||
uint32_t math_rand_seed;
|
||||
|
||||
lv_event_t * event_header;
|
||||
uint32_t event_last_register_id;
|
||||
|
||||
lv_timer_state_t timer_state;
|
||||
lv_anim_state_t anim_state;
|
||||
lv_tick_state_t tick_state;
|
||||
|
||||
lv_draw_buf_handlers_t draw_buf_handlers;
|
||||
lv_draw_buf_handlers_t font_draw_buf_handlers;
|
||||
lv_draw_buf_handlers_t image_cache_draw_buf_handlers; /**< Ensure that all assigned draw buffers
|
||||
* can be managed by image cache. */
|
||||
|
||||
lv_ll_t img_decoder_ll;
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_t img_decoder_info_lock;
|
||||
lv_mutex_t img_decoder_open_lock;
|
||||
#endif
|
||||
|
||||
lv_cache_t * img_cache;
|
||||
lv_cache_t * img_header_cache;
|
||||
|
||||
lv_draw_global_info_t draw_info;
|
||||
lv_ll_t draw_sw_blend_handler_ll;
|
||||
#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0
|
||||
lv_draw_sw_shadow_cache_t sw_shadow_cache;
|
||||
#endif
|
||||
#if LV_DRAW_SW_COMPLEX
|
||||
lv_draw_sw_mask_radius_circle_dsc_arr_t sw_circle_cache;
|
||||
#endif
|
||||
|
||||
#if LV_USE_LOG
|
||||
lv_log_print_g_cb_t custom_log_print_cb;
|
||||
#endif
|
||||
|
||||
#if LV_USE_LOG && LV_LOG_USE_TIMESTAMP
|
||||
uint32_t log_last_log_time;
|
||||
#endif
|
||||
|
||||
#if LV_USE_THEME_SIMPLE
|
||||
void * theme_simple;
|
||||
#endif
|
||||
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
void * theme_default;
|
||||
#endif
|
||||
|
||||
#if LV_USE_THEME_MONO
|
||||
void * theme_mono;
|
||||
#endif
|
||||
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN
|
||||
lv_tlsf_state_t tlsf_state;
|
||||
#endif
|
||||
|
||||
lv_ll_t fsdrv_ll;
|
||||
#if LV_USE_FS_STDIO != '\0'
|
||||
lv_fs_drv_t stdio_fs_drv;
|
||||
#endif
|
||||
#if LV_USE_FS_POSIX
|
||||
lv_fs_drv_t posix_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_FATFS
|
||||
lv_fs_drv_t fatfs_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_WIN32 != '\0'
|
||||
lv_fs_drv_t win32_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_UEFI
|
||||
lv_fs_drv_t uefi_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_LITTLEFS
|
||||
lv_fs_drv_t littlefs_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_ARDUINO_ESP_LITTLEFS
|
||||
lv_fs_drv_t arduino_esp_littlefs_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_ARDUINO_SD
|
||||
lv_fs_drv_t arduino_sd_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FS_FROGFS
|
||||
lv_fs_drv_t frogfs_fs_drv;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FREETYPE
|
||||
struct _lv_freetype_context_t * ft_context;
|
||||
#endif
|
||||
|
||||
#if LV_USE_FONT_COMPRESSED
|
||||
lv_font_fmt_rle_t font_fmt_rle;
|
||||
#endif
|
||||
|
||||
#if LV_USE_SPAN != 0
|
||||
struct _snippet_stack * span_snippet_stack;
|
||||
#endif
|
||||
|
||||
#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN
|
||||
struct _lv_profiler_builtin_ctx_t * profiler_context;
|
||||
#endif
|
||||
|
||||
|
||||
#if LV_USE_FILE_EXPLORER
|
||||
lv_style_t file_explorer_quick_access_style;
|
||||
size_t file_explorer_count;
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
lv_sysmon_backend_data_t sysmon_mem;
|
||||
#endif
|
||||
|
||||
#if LV_USE_IME_PINYIN != 0
|
||||
size_t ime_cand_len;
|
||||
#endif
|
||||
|
||||
#if LV_USE_OBJ_ID_BUILTIN
|
||||
void * objid_array;
|
||||
uint32_t objid_count;
|
||||
#endif
|
||||
|
||||
#if LV_USE_TEST
|
||||
lv_test_state_t test_state;
|
||||
#endif
|
||||
|
||||
#if LV_USE_TRANSLATION
|
||||
lv_ll_t translation_packs_ll;
|
||||
const char * translation_selected_lang;
|
||||
#endif
|
||||
|
||||
#if LV_USE_NUTTX
|
||||
struct _lv_nuttx_ctx_t * nuttx_ctx;
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_t lv_general_mutex;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
lv_linux_proc_stat_t linux_last_proc_stat;
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
uint64_t linux_last_self_proc_time_ticks;
|
||||
lv_linux_proc_stat_t linux_last_system_total_ticks_stat;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS == LV_OS_FREERTOS
|
||||
uint32_t freertos_idle_time_sum;
|
||||
uint32_t freertos_non_idle_time_sum;
|
||||
uint32_t freertos_task_switch_timestamp;
|
||||
bool freertos_idle_task_running;
|
||||
#endif
|
||||
|
||||
#if LV_USE_EVDEV
|
||||
lv_evdev_discovery_t * evdev_discovery;
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_EVE
|
||||
lv_draw_eve_unit_t * draw_eve_unit;
|
||||
#endif
|
||||
} lv_global_t;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#if LV_ENABLE_GLOBAL_CUSTOM
|
||||
#include LV_GLOBAL_CUSTOM_INCLUDE
|
||||
|
||||
#ifndef LV_GLOBAL_CUSTOM
|
||||
#define LV_GLOBAL_CUSTOM() lv_global_default()
|
||||
#endif
|
||||
#define LV_GLOBAL_DEFAULT() LV_GLOBAL_CUSTOM()
|
||||
#else
|
||||
LV_ATTRIBUTE_EXTERN_DATA extern lv_global_t lv_global;
|
||||
#define LV_GLOBAL_DEFAULT() (&lv_global)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
#if LV_ENABLE_GLOBAL_CUSTOM
|
||||
/**
|
||||
* Get the default global object for current thread
|
||||
* @return pointer to the default global object
|
||||
*/
|
||||
lv_global_t * lv_global_default(void);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GLOBAL_H*/
|
||||
566
inc/lvgl/src/core/lv_group.c
Normal file
566
inc/lvgl/src/core/lv_group.c
Normal file
@@ -0,0 +1,566 @@
|
||||
/**
|
||||
* @file lv_group.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_group_private.h"
|
||||
#include "../core/lv_obj_private.h"
|
||||
#include "../core/lv_global.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define default_group LV_GLOBAL_DEFAULT()->group_default
|
||||
#define group_ll_p &(LV_GLOBAL_DEFAULT()->group_ll)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_group_init(void)
|
||||
{
|
||||
lv_ll_init(group_ll_p, sizeof(lv_group_t));
|
||||
}
|
||||
|
||||
void lv_group_deinit(void)
|
||||
{
|
||||
lv_ll_clear(group_ll_p);
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = lv_ll_ins_head(group_ll_p);
|
||||
LV_ASSERT_MALLOC(group);
|
||||
if(group == NULL) return NULL;
|
||||
lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *));
|
||||
|
||||
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;
|
||||
group->user_data = NULL;
|
||||
#if LV_USE_EXT_DATA
|
||||
group->ext_data.free_cb = NULL;
|
||||
group->ext_data.data = NULL;
|
||||
#endif
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void lv_group_delete(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
LV_ASSERT_NULL(group);
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
/*Remove the group from any indev devices */
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_group(indev) == group) {
|
||||
lv_indev_set_group(indev, NULL);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
/*If the group is the default group, set the default group as NULL*/
|
||||
if(group == lv_group_get_default()) lv_group_set_default(NULL);
|
||||
|
||||
lv_ll_clear(&(group->obj_ll));
|
||||
lv_ll_remove(group_ll_p, group);
|
||||
#if LV_USE_EXT_DATA
|
||||
if(group->ext_data.free_cb) {
|
||||
group->ext_data.free_cb(group->ext_data.data);
|
||||
group->ext_data.data = NULL;
|
||||
}
|
||||
#endif
|
||||
lv_free(group);
|
||||
}
|
||||
|
||||
void lv_group_set_default(lv_group_t * group)
|
||||
{
|
||||
default_group = group;
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_get_default(void)
|
||||
{
|
||||
return default_group;
|
||||
}
|
||||
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Be sure the object is removed from its current group*/
|
||||
lv_group_remove_obj(obj);
|
||||
|
||||
if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->group_p = group;
|
||||
|
||||
lv_obj_t ** next = lv_ll_ins_tail(&group->obj_ll);
|
||||
LV_ASSERT_MALLOC(next);
|
||||
if(next == NULL) return;
|
||||
*next = obj;
|
||||
|
||||
/*If the head and the tail is equal then there is only one object in the linked list.
|
||||
*In this case automatically activate it*/
|
||||
if(lv_ll_get_head(&group->obj_ll) == next) {
|
||||
lv_group_refocus(group);
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
lv_group_t * g1 = lv_obj_get_group(obj1);
|
||||
lv_group_t * g2 = lv_obj_get_group(obj2);
|
||||
if(g1 != g2) return;
|
||||
if(g1 == NULL) return;
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
LV_LL_READ(&g1->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj1)(*obj_i) = obj2;
|
||||
else if((*obj_i) == obj2)(*obj_i) = obj1;
|
||||
}
|
||||
|
||||
lv_obj_t * focused = lv_group_get_focused(g1);
|
||||
if(focused == obj1) lv_group_focus_obj(obj2);
|
||||
else if(focused == obj2) lv_group_focus_obj(obj1);
|
||||
|
||||
}
|
||||
|
||||
void lv_group_remove_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Focus on the next object*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
if(g->frozen) g->frozen = 0;
|
||||
|
||||
/*If this is the only object in the group then focus to nothing.*/
|
||||
if(lv_ll_get_head(&g->obj_ll) == g->obj_focus && lv_ll_get_tail(&g->obj_ll) == g->obj_focus) {
|
||||
lv_obj_send_event(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
}
|
||||
/*If there more objects in the group then focus to the next/prev object*/
|
||||
else {
|
||||
lv_group_refocus(g);
|
||||
}
|
||||
}
|
||||
|
||||
/*If the focuses object is still the same then it was the only object in the group but it will
|
||||
*be deleted. Set the `obj_focus` to NULL to get back to the initial state of the group with
|
||||
*zero objects*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
g->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Search the object and remove it from its group*/
|
||||
lv_obj_t ** i;
|
||||
LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
lv_ll_remove(&g->obj_ll, i);
|
||||
lv_free(i);
|
||||
if(obj->spec_attr) obj->spec_attr->group_p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_remove_all_objs(lv_group_t * group)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
group->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
lv_ll_clear(&(group->obj_ll));
|
||||
}
|
||||
|
||||
void lv_group_focus_obj(lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return;
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
if(g->frozen != 0) return;
|
||||
|
||||
/*On defocus edit mode must be leaved*/
|
||||
lv_group_set_editing(g, false);
|
||||
|
||||
lv_obj_t ** i;
|
||||
LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
if(g->obj_focus != NULL && obj != *g->obj_focus) { /*Do not defocus if the same object needs to be focused again*/
|
||||
lv_result_t res = lv_obj_send_event(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
if(res != LV_RESULT_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
|
||||
g->obj_focus = i;
|
||||
|
||||
if(g->obj_focus != NULL) {
|
||||
if(g->focus_cb) g->focus_cb(g);
|
||||
lv_result_t res = lv_obj_send_event(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g));
|
||||
if(res != LV_RESULT_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_next(lv_group_t * group)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
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)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
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)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
if(en == false) group->frozen = 0;
|
||||
else group->frozen = 1;
|
||||
}
|
||||
|
||||
lv_result_t lv_group_send_data(lv_group_t * group, uint32_t c)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
lv_obj_t * act = lv_group_get_focused(group);
|
||||
if(act == NULL) return LV_RESULT_OK;
|
||||
|
||||
if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RESULT_OK;
|
||||
|
||||
return lv_obj_send_event(act, LV_EVENT_KEY, &c);
|
||||
}
|
||||
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
|
||||
group->focus_cb = focus_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
|
||||
group->edge_cb = edge_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
uint8_t en_val = edit ? 1 : 0;
|
||||
|
||||
if(en_val == group->editing) return; /*Do not set the same mode again*/
|
||||
|
||||
group->editing = en_val;
|
||||
lv_obj_t * focused = lv_group_get_focused(group);
|
||||
|
||||
if(focused) {
|
||||
lv_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RESULT_OK) return;
|
||||
|
||||
lv_obj_invalidate(focused);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
group->refocus_policy = policy & 0x01;
|
||||
}
|
||||
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
group->wrap = en ? 1 : 0;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
if(group->obj_focus == NULL) return NULL;
|
||||
|
||||
return *group->obj_focus;
|
||||
}
|
||||
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
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;
|
||||
return group->editing;
|
||||
}
|
||||
|
||||
bool lv_group_get_wrap(lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->wrap;
|
||||
}
|
||||
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group)
|
||||
{
|
||||
LV_ASSERT_NULL(group);
|
||||
return lv_ll_get_len(&group->obj_ll);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_group_get_obj_by_index(lv_group_t * group, uint32_t index)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
lv_obj_t ** obj;
|
||||
|
||||
LV_LL_READ(&group->obj_ll, obj) {
|
||||
if(len == index) {
|
||||
return *obj;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t lv_group_get_count(void)
|
||||
{
|
||||
return lv_ll_get_len(group_ll_p);
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_by_index(uint32_t index)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
lv_group_t * group;
|
||||
|
||||
LV_LL_READ_BACK(group_ll_p, group) {
|
||||
if(len == index) {
|
||||
return group;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
void lv_group_set_external_data(lv_group_t * group, void * data, void (* free_cb)(void * data))
|
||||
{
|
||||
if(!group) {
|
||||
LV_LOG_WARN("Can't attach external user data and destructor callback to a NULL group");
|
||||
return;
|
||||
}
|
||||
|
||||
group->ext_data.data = data;
|
||||
group->ext_data.free_cb = free_cb;
|
||||
}
|
||||
#endif
|
||||
|
||||
void lv_group_set_user_data(lv_group_t * group, void * user_data)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
group->user_data = user_data;
|
||||
}
|
||||
|
||||
void * lv_group_get_user_data(const lv_group_t * group)
|
||||
{
|
||||
if(group == NULL) return NULL;
|
||||
return group->user_data;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_group_refocus(lv_group_t * g)
|
||||
{
|
||||
/*Refocus must temporarily allow wrapping to work correctly*/
|
||||
uint8_t temp_wrap = g->wrap;
|
||||
g->wrap = 1;
|
||||
|
||||
if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_NEXT)
|
||||
lv_group_focus_next(g);
|
||||
else if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_PREV)
|
||||
lv_group_focus_prev(g);
|
||||
/*Restore wrap property*/
|
||||
g->wrap = temp_wrap;
|
||||
}
|
||||
|
||||
static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *))
|
||||
{
|
||||
bool focus_changed = false;
|
||||
if(group->frozen) return focus_changed;
|
||||
|
||||
lv_obj_t ** obj_next = group->obj_focus;
|
||||
lv_obj_t ** obj_sentinel = NULL;
|
||||
bool can_move = true;
|
||||
bool can_begin = true;
|
||||
|
||||
for(;;) {
|
||||
if(obj_next == NULL) {
|
||||
if(group->wrap || obj_sentinel == NULL) {
|
||||
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 focus_changed;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj_sentinel == NULL) {
|
||||
obj_sentinel = obj_next;
|
||||
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 focus_changed;
|
||||
}
|
||||
|
||||
can_move = true;
|
||||
|
||||
if(obj_next == NULL) continue;
|
||||
if(lv_obj_get_state(*obj_next) & LV_STATE_DISABLED) continue;
|
||||
|
||||
/*Hidden objects don't receive focus.
|
||||
*If any parent is hidden, the object is also hidden)*/
|
||||
lv_obj_t * parent = *obj_next;
|
||||
while(parent) {
|
||||
if(lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) break;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
|
||||
if(parent && lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) continue;
|
||||
|
||||
/*If we got her a good candidate is found*/
|
||||
break;
|
||||
}
|
||||
|
||||
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_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
if(res != LV_RESULT_OK) return focus_changed;
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
lv_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RESULT_OK) return focus_changed;
|
||||
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
focus_changed = true;
|
||||
return focus_changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an indev preferably with POINTER type (because it's the most generic) that uses the given group.
|
||||
* In other words, find an indev, that is related to the given group.
|
||||
* In the worst case simply return the latest indev
|
||||
* @param g a group the find in the indevs
|
||||
* @return the suggested indev
|
||||
*/
|
||||
static lv_indev_t * get_indev(const lv_group_t * g)
|
||||
{
|
||||
lv_indev_t * indev_guess = NULL;
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
|
||||
while(indev) {
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
/*Prefer POINTER*/
|
||||
if(indev_type == LV_INDEV_TYPE_POINTER) return indev;
|
||||
if(lv_indev_get_group(indev) == g) {
|
||||
indev_guess = indev;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
return indev_guess;
|
||||
}
|
||||
278
inc/lvgl/src/core/lv_group.h
Normal file
278
inc/lvgl/src/core/lv_group.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* @file lv_group.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_H
|
||||
#define LV_GROUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_ll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/** Predefined keys to control which Widget has focus via lv_group_send(group, c) */
|
||||
typedef enum {
|
||||
LV_KEY_UP = 17, /*0x11*/
|
||||
LV_KEY_DOWN = 18, /*0x12*/
|
||||
LV_KEY_RIGHT = 19, /*0x13*/
|
||||
LV_KEY_LEFT = 20, /*0x14*/
|
||||
LV_KEY_ESC = 27, /*0x1B*/
|
||||
LV_KEY_DEL = 127, /*0x7F*/
|
||||
LV_KEY_BACKSPACE = 8, /*0x08*/
|
||||
LV_KEY_ENTER = 10, /*0x0A, '\n'*/
|
||||
LV_KEY_NEXT = 9, /*0x09, '\t'*/
|
||||
LV_KEY_PREV = 11, /*0x0B, '*/
|
||||
LV_KEY_HOME = 2, /*0x02, STX*/
|
||||
LV_KEY_END = 3, /*0x03, ETX*/
|
||||
} lv_key_t;
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef void (*lv_group_focus_cb_t)(lv_group_t *);
|
||||
typedef void (*lv_group_edge_cb_t)(lv_group_t *, bool);
|
||||
|
||||
typedef enum {
|
||||
LV_GROUP_REFOCUS_POLICY_NEXT = 0,
|
||||
LV_GROUP_REFOCUS_POLICY_PREV = 1
|
||||
} lv_group_refocus_policy_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create new Widget group.
|
||||
* @return pointer to the new Widget group
|
||||
*/
|
||||
lv_group_t * lv_group_create(void);
|
||||
|
||||
/**
|
||||
* Delete group object.
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_delete(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Set default group. New Widgets will be added to this group if it's enabled in
|
||||
* their class with `add_to_def_group = true`.
|
||||
* @param group pointer to a group (can be `NULL`)
|
||||
*/
|
||||
void lv_group_set_default(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get default group.
|
||||
* @return pointer to the default group
|
||||
*/
|
||||
lv_group_t * lv_group_get_default(void);
|
||||
|
||||
/**
|
||||
* Add an Widget to group.
|
||||
* @param group pointer to a group
|
||||
* @param obj pointer to a Widget to add
|
||||
*/
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Swap 2 Widgets in group. Widgets must be in the same group.
|
||||
* @param obj1 pointer to a Widget
|
||||
* @param obj2 pointer to another Widget
|
||||
*/
|
||||
void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2);
|
||||
|
||||
/**
|
||||
* Remove a Widget from its group.
|
||||
* @param obj pointer to Widget to remove
|
||||
*/
|
||||
void lv_group_remove_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Remove all Widgets from a group.
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_remove_all_objs(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Focus on a Widget (defocus the current).
|
||||
* @param obj pointer to Widget to focus on
|
||||
*/
|
||||
void lv_group_focus_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Focus on next Widget in a group (defocus the current).
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_next(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Focus on previous Widget in a group (defocus the current).
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_prev(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Do not allow changing focus from current Widget.
|
||||
* @param group pointer to a group
|
||||
* @param en true: freeze, false: release freezing (normal mode)
|
||||
*/
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Send a control character to Widget that has focus in a group.
|
||||
* @param group pointer to a group
|
||||
* @param c a character (use LV_KEY_.. to navigate)
|
||||
* @return result of Widget with focus in group.
|
||||
*/
|
||||
lv_result_t lv_group_send_data(lv_group_t * group, uint32_t c);
|
||||
|
||||
/**
|
||||
* Set a function for a group which will be called when a new Widget has focus.
|
||||
* @param group pointer to a group
|
||||
* @param focus_cb the call back function or NULL if unused
|
||||
*/
|
||||
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 Widget in a group gets focus when Widget that has
|
||||
* focus is deleted.
|
||||
* @param group pointer to a group
|
||||
* @param policy new refocus policy enum
|
||||
*/
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy);
|
||||
|
||||
/**
|
||||
* Manually set the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @param edit true: edit mode; false: navigate mode
|
||||
*/
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit);
|
||||
|
||||
/**
|
||||
* Set whether moving focus to next/previous Widget will allow wrapping from
|
||||
* first->last or last->first Widget.
|
||||
* @param group pointer to group
|
||||
* @param en true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Get Widget that has focus, or NULL if there isn't one.
|
||||
* @param group pointer to a group
|
||||
* @return pointer to Widget with focus
|
||||
*/
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get focus callback function of a group.
|
||||
* @param group pointer to a group
|
||||
* @return the call back function or NULL if not set
|
||||
*/
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get 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 current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @return true: edit mode; false: navigate mode
|
||||
*/
|
||||
bool lv_group_get_editing(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get whether moving focus to next/previous Widget will allow wrapping from
|
||||
* first->last or last->first Widget.
|
||||
* @param group pointer to group
|
||||
*/
|
||||
bool lv_group_get_wrap(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get number of Widgets in group.
|
||||
* @param group pointer to a group
|
||||
* @return number of Widgets in the group
|
||||
*/
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get nth Widget within group.
|
||||
* @param group pointer to a group
|
||||
* @param index index of Widget within the group
|
||||
* @return pointer to Widget
|
||||
*/
|
||||
lv_obj_t * lv_group_get_obj_by_index(lv_group_t * group, uint32_t index);
|
||||
|
||||
/**
|
||||
* Get the number of groups.
|
||||
* @return number of groups
|
||||
*/
|
||||
uint32_t lv_group_get_count(void);
|
||||
|
||||
/**
|
||||
* Get a group by its index.
|
||||
* @param index index of the group
|
||||
* @return pointer to the group
|
||||
*/
|
||||
lv_group_t * lv_group_by_index(uint32_t index);
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
/**
|
||||
* @brief Attaches external user data and destructor callback to a group
|
||||
*
|
||||
* Associates custom user data with an LVGL group and specifies a destructor function
|
||||
* that will be automatically invoked when the group is deleted to properly clean up
|
||||
* the associated resources.
|
||||
*
|
||||
* @param group Pointer to a group
|
||||
* @param data User-defined data pointer to associate with a group
|
||||
* @param free_cb Callback function for cleaning up ext_data when group is deleted.
|
||||
* Receives ext_data as parameter. NULL means no cleanup required.
|
||||
*/
|
||||
void lv_group_set_external_data(lv_group_t * group, void * data, void (* free_cb)(void * data));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set user data to the group
|
||||
* @param group pointer to a group
|
||||
* @param user_data pointer to user data
|
||||
*/
|
||||
void lv_group_set_user_data(lv_group_t * group, void * user_data);
|
||||
|
||||
/**
|
||||
* Get a pointer to the user data of the group
|
||||
* @param indev pointer to a group
|
||||
* @return pointer to the user data or NULL if group is NULL
|
||||
*/
|
||||
void * lv_group_get_user_data(const lv_group_t * group);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GROUP_H*/
|
||||
78
inc/lvgl/src/core/lv_group_private.h
Normal file
78
inc/lvgl/src/core/lv_group_private.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_group_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_PRIVATE_H
|
||||
#define LV_GROUP_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_ext_data.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Groups can be used to logically hold objects so that they can be individually focused.
|
||||
* They are NOT for laying out objects on a screen (try layouts for that).
|
||||
*/
|
||||
struct _lv_group_t {
|
||||
#if LV_USE_EXT_DATA
|
||||
lv_ext_data_t ext_data;
|
||||
#endif
|
||||
lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/
|
||||
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) */
|
||||
|
||||
void * user_data;
|
||||
|
||||
uint8_t frozen : 1; /**< 1: can't focus to new object*/
|
||||
uint8_t editing : 1; /**< 1: Edit mode, 0: Navigate mode*/
|
||||
uint8_t refocus_policy : 1; /**< 1: Focus prev if focused on deletion. 0: Focus next if focused on
|
||||
deletion.*/
|
||||
uint8_t wrap : 1; /**< 1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end
|
||||
of list.*/
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init the group module
|
||||
* @remarks Internal function, do not call directly.
|
||||
*/
|
||||
void lv_group_init(void);
|
||||
|
||||
/**
|
||||
* Deinit the group module
|
||||
* @remarks Internal function, do not call directly.
|
||||
*/
|
||||
void lv_group_deinit(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GROUP_PRIVATE_H*/
|
||||
1342
inc/lvgl/src/core/lv_obj.c
Normal file
1342
inc/lvgl/src/core/lv_obj.c
Normal file
File diff suppressed because it is too large
Load Diff
501
inc/lvgl/src/core/lv_obj.h
Normal file
501
inc/lvgl/src/core/lv_obj.h
Normal file
@@ -0,0 +1,501 @@
|
||||
/**
|
||||
* @file lv_obj.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_H
|
||||
#define LV_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
|
||||
#include "lv_obj_tree.h"
|
||||
#include "lv_obj_pos.h"
|
||||
#include "lv_obj_scroll.h"
|
||||
#include "lv_obj_style.h"
|
||||
#include "lv_obj_draw.h"
|
||||
#include "lv_obj_class.h"
|
||||
#include "lv_obj_event.h"
|
||||
#include "lv_obj_property.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/**
|
||||
* On/Off features controlling the object's behavior.
|
||||
* OR-ed values are possible
|
||||
*
|
||||
* Note: update obj flags corresponding properties below
|
||||
* whenever add/remove flags or change bit definition of flags.
|
||||
*/
|
||||
typedef enum {
|
||||
LV_OBJ_FLAG_HIDDEN = (1u << 0), /**< Make the object hidden. (Like it wasn't there at all)*/
|
||||
LV_OBJ_FLAG_CLICKABLE = (1u << 1), /**< Make the object clickable by the input devices*/
|
||||
LV_OBJ_FLAG_CLICK_FOCUSABLE = (1u << 2), /**< Add focused state to the object when clicked*/
|
||||
LV_OBJ_FLAG_CHECKABLE = (1u << 3), /**< Toggle checked state when the object is clicked*/
|
||||
LV_OBJ_FLAG_SCROLLABLE = (1u << 4), /**< Make the object scrollable*/
|
||||
LV_OBJ_FLAG_SCROLL_ELASTIC = (1u << 5), /**< Allow scrolling inside but with slower speed*/
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1u << 6), /**< Make the object scroll further when "thrown"*/
|
||||
LV_OBJ_FLAG_SCROLL_ONE = (1u << 7), /**< Allow scrolling only one snappable children*/
|
||||
LV_OBJ_FLAG_SCROLL_CHAIN_HOR = (1u << 8), /**< Allow propagating the horizontal scroll to a parent*/
|
||||
LV_OBJ_FLAG_SCROLL_CHAIN_VER = (1u << 9), /**< Allow propagating the vertical scroll to a parent*/
|
||||
LV_OBJ_FLAG_SCROLL_CHAIN = (LV_OBJ_FLAG_SCROLL_CHAIN_HOR | LV_OBJ_FLAG_SCROLL_CHAIN_VER),
|
||||
LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1u << 10), /**< Automatically scroll object to make it visible when focused*/
|
||||
LV_OBJ_FLAG_SCROLL_WITH_ARROW = (1u << 11), /**< Allow scrolling the focused object with arrow keys*/
|
||||
LV_OBJ_FLAG_SNAPPABLE = (1u << 12), /**< If scroll snap is enabled on the parent it can snap to this object*/
|
||||
LV_OBJ_FLAG_PRESS_LOCK = (1u << 13), /**< Keep the object pressed even if the press slid from the object*/
|
||||
LV_OBJ_FLAG_EVENT_BUBBLE = (1u << 14), /**< Propagate the events to the parent too*/
|
||||
LV_OBJ_FLAG_GESTURE_BUBBLE = (1u << 15), /**< Propagate the gestures to the parent*/
|
||||
LV_OBJ_FLAG_ADV_HITTEST = (1u << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
|
||||
LV_OBJ_FLAG_IGNORE_LAYOUT = (1u << 17), /**< Make the object not positioned by the layouts*/
|
||||
LV_OBJ_FLAG_FLOATING = (1u << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
|
||||
LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS = (1u << 19), /**< Send `LV_EVENT_DRAW_TASK_ADDED` events*/
|
||||
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1u << 20),/**< Do not clip the children to the parent's ext draw size*/
|
||||
LV_OBJ_FLAG_EVENT_TRICKLE = (1u << 21), /**< Propagate the events to the children too*/
|
||||
LV_OBJ_FLAG_STATE_TRICKLE = (1u << 22), /**< Propagate the states to the children too*/
|
||||
|
||||
LV_OBJ_FLAG_LAYOUT_1 = (1u << 23), /**< Custom flag, free to use by layouts*/
|
||||
LV_OBJ_FLAG_LAYOUT_2 = (1u << 24), /**< Custom flag, free to use by layouts*/
|
||||
#if LV_USE_FLEX
|
||||
LV_OBJ_FLAG_FLEX_IN_NEW_TRACK = LV_OBJ_FLAG_LAYOUT_1, /**< Start a new flex track on this item*/
|
||||
#endif
|
||||
|
||||
LV_OBJ_FLAG_WIDGET_1 = (1u << 25), /**< Custom flag, free to use by widget*/
|
||||
LV_OBJ_FLAG_WIDGET_2 = (1u << 26), /**< Custom flag, free to use by widget*/
|
||||
LV_OBJ_FLAG_USER_1 = (1u << 27), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_2 = (1u << 28), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_3 = (1u << 29), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_4 = (1u << 30), /**< Custom flag, free to use by user*/
|
||||
} lv_obj_flag_t;
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
enum _lv_signed_prop_id_t {
|
||||
/*OBJ flag properties */
|
||||
LV_PROPERTY_ID(OBJ, FLAG_START, LV_PROPERTY_TYPE_INT, 0),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_HIDDEN, LV_PROPERTY_TYPE_INT, 0),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_CLICKABLE, LV_PROPERTY_TYPE_INT, 1),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_CLICK_FOCUSABLE, LV_PROPERTY_TYPE_INT, 2),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_CHECKABLE, LV_PROPERTY_TYPE_INT, 3),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLLABLE, LV_PROPERTY_TYPE_INT, 4),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ELASTIC, LV_PROPERTY_TYPE_INT, 5),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_MOMENTUM, LV_PROPERTY_TYPE_INT, 6),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ONE, LV_PROPERTY_TYPE_INT, 7),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_CHAIN_HOR, LV_PROPERTY_TYPE_INT, 8),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_CHAIN_VER, LV_PROPERTY_TYPE_INT, 9),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ON_FOCUS, LV_PROPERTY_TYPE_INT, 10),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SCROLL_WITH_ARROW, LV_PROPERTY_TYPE_INT, 11),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SNAPPABLE, LV_PROPERTY_TYPE_INT, 12),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_PRESS_LOCK, LV_PROPERTY_TYPE_INT, 13),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_EVENT_BUBBLE, LV_PROPERTY_TYPE_INT, 14),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_GESTURE_BUBBLE, LV_PROPERTY_TYPE_INT, 15),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_ADV_HITTEST, LV_PROPERTY_TYPE_INT, 16),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_IGNORE_LAYOUT, LV_PROPERTY_TYPE_INT, 17),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_FLOATING, LV_PROPERTY_TYPE_INT, 18),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_SEND_DRAW_TASK_EVENTS, LV_PROPERTY_TYPE_INT, 19),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_OVERFLOW_VISIBLE, LV_PROPERTY_TYPE_INT, 20),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_EVENT_TRICKLE, LV_PROPERTY_TYPE_INT, 21),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_STATE_TRICKLE, LV_PROPERTY_TYPE_INT, 22),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_1, LV_PROPERTY_TYPE_INT, 23),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_2, LV_PROPERTY_TYPE_INT, 24),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_FLEX_IN_NEW_TRACK, LV_PROPERTY_TYPE_INT, 23), /*Mapped to FLAG_LAYOUT_1*/
|
||||
LV_PROPERTY_ID(OBJ, FLAG_WIDGET_1, LV_PROPERTY_TYPE_INT, 25),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_WIDGET_2, LV_PROPERTY_TYPE_INT, 26),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_USER_1, LV_PROPERTY_TYPE_INT, 27),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_USER_2, LV_PROPERTY_TYPE_INT, 28),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_USER_3, LV_PROPERTY_TYPE_INT, 29),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_USER_4, LV_PROPERTY_TYPE_INT, 30),
|
||||
LV_PROPERTY_ID(OBJ, FLAG_END, LV_PROPERTY_TYPE_INT, 30),
|
||||
|
||||
LV_PROPERTY_ID(OBJ, STATE_START, LV_PROPERTY_TYPE_INT, 31),
|
||||
LV_PROPERTY_ID(OBJ, STATE_ALT, LV_PROPERTY_TYPE_INT, 31),
|
||||
/*1 reserved*/
|
||||
LV_PROPERTY_ID(OBJ, STATE_CHECKED, LV_PROPERTY_TYPE_INT, 33),
|
||||
LV_PROPERTY_ID(OBJ, STATE_FOCUSED, LV_PROPERTY_TYPE_INT, 34),
|
||||
LV_PROPERTY_ID(OBJ, STATE_FOCUS_KEY, LV_PROPERTY_TYPE_INT, 35),
|
||||
LV_PROPERTY_ID(OBJ, STATE_EDITED, LV_PROPERTY_TYPE_INT, 36),
|
||||
LV_PROPERTY_ID(OBJ, STATE_HOVERED, LV_PROPERTY_TYPE_INT, 37),
|
||||
LV_PROPERTY_ID(OBJ, STATE_PRESSED, LV_PROPERTY_TYPE_INT, 38),
|
||||
LV_PROPERTY_ID(OBJ, STATE_SCROLLED, LV_PROPERTY_TYPE_INT, 39),
|
||||
LV_PROPERTY_ID(OBJ, STATE_DISABLED, LV_PROPERTY_TYPE_INT, 40),
|
||||
/*2 reserved*/
|
||||
LV_PROPERTY_ID(OBJ, STATE_USER_1, LV_PROPERTY_TYPE_INT, 43),
|
||||
LV_PROPERTY_ID(OBJ, STATE_USER_2, LV_PROPERTY_TYPE_INT, 44),
|
||||
LV_PROPERTY_ID(OBJ, STATE_USER_3, LV_PROPERTY_TYPE_INT, 45),
|
||||
LV_PROPERTY_ID(OBJ, STATE_USER_4, LV_PROPERTY_TYPE_INT, 46),
|
||||
LV_PROPERTY_ID(OBJ, STATE_ANY, LV_PROPERTY_TYPE_INT, 47),
|
||||
LV_PROPERTY_ID(OBJ, STATE_END, LV_PROPERTY_TYPE_INT, 47),
|
||||
|
||||
/*OBJ normal properties*/
|
||||
LV_PROPERTY_ID(OBJ, PARENT, LV_PROPERTY_TYPE_OBJ, 48),
|
||||
LV_PROPERTY_ID(OBJ, X, LV_PROPERTY_TYPE_INT, 49),
|
||||
LV_PROPERTY_ID(OBJ, Y, LV_PROPERTY_TYPE_INT, 50),
|
||||
LV_PROPERTY_ID(OBJ, W, LV_PROPERTY_TYPE_INT, 51),
|
||||
LV_PROPERTY_ID(OBJ, H, LV_PROPERTY_TYPE_INT, 52),
|
||||
LV_PROPERTY_ID(OBJ, CONTENT_WIDTH, LV_PROPERTY_TYPE_INT, 53),
|
||||
LV_PROPERTY_ID(OBJ, CONTENT_HEIGHT, LV_PROPERTY_TYPE_INT, 54),
|
||||
LV_PROPERTY_ID(OBJ, LAYOUT, LV_PROPERTY_TYPE_INT, 55),
|
||||
LV_PROPERTY_ID(OBJ, ALIGN, LV_PROPERTY_TYPE_INT, 56),
|
||||
LV_PROPERTY_ID(OBJ, SCROLLBAR_MODE, LV_PROPERTY_TYPE_INT, 57),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_DIR, LV_PROPERTY_TYPE_INT, 58),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_SNAP_X, LV_PROPERTY_TYPE_INT, 59),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_SNAP_Y, LV_PROPERTY_TYPE_INT, 60),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_X, LV_PROPERTY_TYPE_INT, 61),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_Y, LV_PROPERTY_TYPE_INT, 62),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_TOP, LV_PROPERTY_TYPE_INT, 63),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_BOTTOM, LV_PROPERTY_TYPE_INT, 64),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_LEFT, LV_PROPERTY_TYPE_INT, 65),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_RIGHT, LV_PROPERTY_TYPE_INT, 66),
|
||||
LV_PROPERTY_ID(OBJ, SCROLL_END, LV_PROPERTY_TYPE_POINT, 67),
|
||||
LV_PROPERTY_ID(OBJ, EXT_DRAW_SIZE, LV_PROPERTY_TYPE_INT, 68),
|
||||
LV_PROPERTY_ID(OBJ, EVENT_COUNT, LV_PROPERTY_TYPE_INT, 69),
|
||||
LV_PROPERTY_ID(OBJ, SCREEN, LV_PROPERTY_TYPE_OBJ, 70),
|
||||
LV_PROPERTY_ID(OBJ, DISPLAY, LV_PROPERTY_TYPE_POINTER, 71),
|
||||
LV_PROPERTY_ID(OBJ, CHILD_COUNT, LV_PROPERTY_TYPE_INT, 72),
|
||||
LV_PROPERTY_ID(OBJ, INDEX, LV_PROPERTY_TYPE_INT, 73),
|
||||
|
||||
LV_PROPERTY_OBJ_END,
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Make the base object's class publicly available.
|
||||
*/
|
||||
LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_obj_class;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a base object (a rectangle)
|
||||
* @param parent pointer to a parent object. If NULL then a screen will be created.
|
||||
* @return pointer to the new object
|
||||
*/
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set one or more flags
|
||||
* @param obj pointer to an object
|
||||
* @param f OR-ed values from `lv_obj_flag_t` to set.
|
||||
*/
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Remove one or more flags
|
||||
* @param obj pointer to an object
|
||||
* @param f OR-ed values from `lv_obj_flag_t` to clear.
|
||||
*/
|
||||
void lv_obj_remove_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Set add or remove one or more flags.
|
||||
* @param obj pointer to an object
|
||||
* @param f OR-ed values from `lv_obj_flag_t` to update.
|
||||
* @param v true: add the flags; false: remove the flags
|
||||
*/
|
||||
void lv_obj_set_flag(lv_obj_t * obj, lv_obj_flag_t f, bool v);
|
||||
|
||||
/**
|
||||
* Add one or more states to the object. The other state bits will remain unchanged.
|
||||
* If specified in the styles, transition animation will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
|
||||
*/
|
||||
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Remove one or more states to the object. The other state bits will remain unchanged.
|
||||
* If specified in the styles, transition animation will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
|
||||
*/
|
||||
void lv_obj_remove_state(lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Add or remove one or more states to the object. The other state bits will remain unchanged.
|
||||
* @param obj pointer to an object
|
||||
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
|
||||
* @param v true: add the states; false: remove the states
|
||||
*/
|
||||
void lv_obj_set_state(lv_obj_t * obj, lv_state_t state, bool v);
|
||||
|
||||
/**
|
||||
* Set the user_data field of the object
|
||||
* @param obj pointer to an object
|
||||
* @param user_data pointer to the new user_data.
|
||||
*/
|
||||
void lv_obj_set_user_data(lv_obj_t * obj, void * user_data);
|
||||
|
||||
|
||||
/** Allow only one RADIO_BUTTON sibling to be checked
|
||||
* @param obj pointer to a widget
|
||||
* @param en enable or disable radio button behavior
|
||||
*/
|
||||
void lv_obj_set_radio_button(lv_obj_t * obj, bool en);
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
/**
|
||||
* Check if a given flag or all the given flags are set on an object.
|
||||
* @param obj pointer to an object
|
||||
* @param f the flag(s) to check (OR-ed values can be used)
|
||||
* @return true: all flags are set; false: not all flags are set
|
||||
*/
|
||||
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Check if a given flag or any of the flags are set on an object.
|
||||
* @param obj pointer to an object
|
||||
* @param f the flag(s) to check (OR-ed values can be used)
|
||||
* @return true: at least one flag is set; false: none of the flags are set
|
||||
*/
|
||||
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Get the state of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the state (OR-ed values from `lv_state_t`)
|
||||
*/
|
||||
lv_state_t lv_obj_get_state(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check if the object is in a given state or not.
|
||||
* @param obj pointer to an object
|
||||
* @param state a state or combination of states to check
|
||||
* @return true: `obj` is in `state`; false: `obj` is not in `state`
|
||||
*/
|
||||
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/** Get whether the object is a radio button
|
||||
* @param obj pointer to a widget
|
||||
* @return true if radio button behavior is enabled
|
||||
*/
|
||||
bool lv_obj_is_radio_button(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the group of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the pointer to group of the object
|
||||
*/
|
||||
lv_group_t * lv_obj_get_group(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the user_data field of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the pointer to the user_data of the object
|
||||
*/
|
||||
void * lv_obj_get_user_data(lv_obj_t * obj);
|
||||
|
||||
/*=======================
|
||||
* Other functions
|
||||
*======================*/
|
||||
|
||||
/**
|
||||
* Allocate special data for an object if not allocated yet.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_allocate_spec_attr(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check the type of obj.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p a class to check (e.g. `lv_slider_class`)
|
||||
* @return true: `class_p` is the `obj` class.
|
||||
*/
|
||||
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Check if any object has a given class (type).
|
||||
* It checks the ancestor classes too.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p a class to check (e.g. `lv_slider_class`)
|
||||
* @return true: `obj` has the given class
|
||||
*/
|
||||
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Get the class (type) of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the class (type) of the object
|
||||
*/
|
||||
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check if any object is still "alive".
|
||||
* @param obj pointer to an object
|
||||
* @return true: valid
|
||||
*/
|
||||
bool lv_obj_is_valid(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Utility to set an object reference to NULL when it gets deleted.
|
||||
* The reference should be in a location that will not become invalid
|
||||
* during the object's lifetime, i.e. static or allocated.
|
||||
* @param obj_ptr a pointer to a pointer to an object
|
||||
*/
|
||||
void lv_obj_null_on_delete(lv_obj_t ** obj_ptr);
|
||||
|
||||
/**
|
||||
* Add an event handler to a widget that will load a screen on a trigger.
|
||||
* @param obj pointer to widget which should load the screen
|
||||
* @param trigger an event code, e.g. `LV_EVENT_CLICKED`
|
||||
* @param screen the screen to load (must be a valid widget)
|
||||
* @param anim_type element of `lv_screen_load_anim_t` the screen load animation
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the screen load in milliseconds
|
||||
*/
|
||||
void lv_obj_add_screen_load_event(lv_obj_t * obj, lv_event_code_t trigger, lv_obj_t * screen,
|
||||
lv_screen_load_anim_t anim_type, uint32_t duration, uint32_t delay);
|
||||
|
||||
/**
|
||||
* Add an event handler to a widget that will create a screen on a trigger.
|
||||
* The created screen will be deleted when it's unloaded
|
||||
* @param obj pointer to widget which should load the screen
|
||||
* @param trigger an event code, e.g. `LV_EVENT_CLICKED`
|
||||
* @param screen_create_cb a callback to create the screen, e.g. `lv_obj_t * myscreen_create(void)`
|
||||
* @param anim_type element of `lv_screen_load_anim_t` the screen load animation
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the screen load in milliseconds
|
||||
*/
|
||||
void lv_obj_add_screen_create_event(lv_obj_t * obj, lv_event_code_t trigger, lv_screen_create_cb_t screen_create_cb,
|
||||
lv_screen_load_anim_t anim_type, uint32_t duration, uint32_t delay);
|
||||
|
||||
|
||||
/**
|
||||
* Play a timeline animation on a trigger
|
||||
* @param obj pointer to widget which should trigger playing the animation
|
||||
* @param trigger an event code, e.g. `LV_EVENT_CLICKED`
|
||||
* @param at pointer to an animation timeline
|
||||
* @param delay wait time before starting the animation
|
||||
* @param reverse true: play in reverse
|
||||
*/
|
||||
void lv_obj_add_play_timeline_event(lv_obj_t * obj, lv_event_code_t trigger, lv_anim_timeline_t * at, uint32_t delay,
|
||||
bool reverse);
|
||||
|
||||
#if LV_USE_OBJ_ID
|
||||
/**
|
||||
* Set an id for an object.
|
||||
* @param obj pointer to an object
|
||||
* @param id the id of the object
|
||||
*/
|
||||
void lv_obj_set_id(lv_obj_t * obj, void * id);
|
||||
|
||||
/**
|
||||
* Get the id of an object.
|
||||
* @param obj pointer to an object
|
||||
* @return the id of the object
|
||||
*/
|
||||
void * lv_obj_get_id(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* DEPRECATED IDs are used only to print the widget trees.
|
||||
* To find a widget use `lv_obj_find_by_name`
|
||||
*
|
||||
* Get the child object by its id.
|
||||
* It will check children and grandchildren recursively.
|
||||
* Function `lv_obj_id_compare` is used to matched obj id with given id.
|
||||
*
|
||||
* @param obj pointer to an object
|
||||
* @param id the id of the child object
|
||||
* @return pointer to the child object or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_obj_find_by_id(const lv_obj_t * obj, const void * id);
|
||||
|
||||
/**
|
||||
* Assign id to object if not previously assigned.
|
||||
* This function gets called automatically when LV_OBJ_ID_AUTO_ASSIGN is enabled.
|
||||
*
|
||||
* Set `LV_USE_OBJ_ID_BUILTIN` to use the builtin method to generate object ID.
|
||||
* Otherwise, these functions including `lv_obj_[set|assign|free|stringify]_id` and
|
||||
* `lv_obj_id_compare`should be implemented externally.
|
||||
*
|
||||
* @param class_p the class this obj belongs to. Note obj->class_p is the class currently being constructed.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Free resources allocated by `lv_obj_assign_id` or `lv_obj_set_id`.
|
||||
* This function is also called automatically when object is deleted.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_free_id(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Compare two obj id, return 0 if they are equal.
|
||||
*
|
||||
* Set `LV_USE_OBJ_ID_BUILTIN` to use the builtin method for compare.
|
||||
* Otherwise, it must be implemented externally.
|
||||
*
|
||||
* @param id1: the first id
|
||||
* @param id2: the second id
|
||||
* @return 0 if they are equal, non-zero otherwise.
|
||||
*/
|
||||
int lv_obj_id_compare(const void * id1, const void * id2);
|
||||
|
||||
/**
|
||||
* Format an object's id into a string.
|
||||
* @param obj pointer to an object
|
||||
* @param buf buffer to write the string into
|
||||
* @param len length of the buffer
|
||||
*/
|
||||
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len);
|
||||
|
||||
#if LV_USE_OBJ_ID_BUILTIN
|
||||
/**
|
||||
* Free resources used by builtin ID generator.
|
||||
*/
|
||||
void lv_objid_builtin_destroy(void);
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_OBJ_ID*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_ASSERT_OBJ
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_class) \
|
||||
do { \
|
||||
LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \
|
||||
LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \
|
||||
LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?"); \
|
||||
} while(0)
|
||||
# else
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_class) LV_ASSERT_NULL(obj_p)
|
||||
#endif
|
||||
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE
|
||||
# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
# define LV_TRACE_OBJ_CREATE(...)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_H*/
|
||||
233
inc/lvgl/src/core/lv_obj_class.c
Normal file
233
inc/lvgl/src/core/lv_obj_class.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file lv_obj_class.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_class_private.h"
|
||||
#include "lv_obj_private.h"
|
||||
#include "../themes/lv_theme.h"
|
||||
#include "../display/lv_display.h"
|
||||
#include "../display/lv_display_private.h"
|
||||
#include "../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_obj_class)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent)
|
||||
{
|
||||
LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);
|
||||
uint32_t s = get_instance_size(class_p);
|
||||
lv_obj_t * obj = lv_malloc_zeroed(s);
|
||||
if(obj == NULL) return NULL;
|
||||
obj->class_p = class_p;
|
||||
obj->parent = parent;
|
||||
|
||||
/*Create a screen*/
|
||||
if(parent == NULL) {
|
||||
LV_TRACE_OBJ_CREATE("creating a screen");
|
||||
lv_display_t * disp = lv_display_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("No display created yet. No place to assign the new screen");
|
||||
lv_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(disp->screens == NULL) {
|
||||
disp->screen_cnt = 0;
|
||||
}
|
||||
|
||||
lv_obj_t ** screens = lv_realloc(disp->screens, sizeof(lv_obj_t *) * (disp->screen_cnt + 1));
|
||||
LV_ASSERT_MALLOC(screens);
|
||||
if(screens == NULL) {
|
||||
lv_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
disp->screen_cnt++;
|
||||
disp->screens = screens;
|
||||
disp->screens[disp->screen_cnt - 1] = obj;
|
||||
|
||||
/*Set coordinates to full screen size*/
|
||||
obj->coords.x1 = 0;
|
||||
obj->coords.y1 = 0;
|
||||
obj->coords.x2 = lv_display_get_horizontal_resolution(NULL) - 1;
|
||||
obj->coords.y2 = lv_display_get_vertical_resolution(NULL) - 1;
|
||||
}
|
||||
/*Create a normal object*/
|
||||
else {
|
||||
LV_TRACE_OBJ_CREATE("creating normal object");
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
if(parent->spec_attr == NULL) {
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
}
|
||||
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_realloc(parent->spec_attr->children,
|
||||
sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
|
||||
parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_obj_class_init_obj(lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return;
|
||||
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
lv_obj_enable_style_refresh(false);
|
||||
|
||||
lv_theme_apply(obj);
|
||||
lv_obj_construct(obj->class_p, obj);
|
||||
|
||||
lv_obj_enable_style_refresh(true);
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
|
||||
lv_obj_refresh_self_size(obj);
|
||||
|
||||
lv_group_t * def_group = lv_group_get_default();
|
||||
if(def_group && lv_obj_is_group_def(obj)) {
|
||||
lv_group_add_obj(def_group, obj);
|
||||
}
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) {
|
||||
/*Call the ancestor's event handler to the parent to notify it about the new child.
|
||||
*Also triggers layout update*/
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj);
|
||||
|
||||
/*Invalidate the area if not screen created*/
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_destruct(lv_obj_t * obj)
|
||||
{
|
||||
#if LV_USE_EXT_DATA
|
||||
if(obj->ext_data.free_cb) {
|
||||
obj->ext_data.free_cb(obj->ext_data.data);
|
||||
obj->ext_data.data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*Don't let the descendant methods run during destructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Call the base class's destructor too*/
|
||||
lv_obj_destruct(obj);
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_is_editable(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which editable is set*/
|
||||
while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE;
|
||||
}
|
||||
|
||||
bool lv_obj_is_group_def(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which group_def is set*/
|
||||
while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE;
|
||||
}
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
void lv_obj_set_external_data(lv_obj_t * obj, void * data, void (* free_cb)(void * data))
|
||||
{
|
||||
if(!obj) {
|
||||
LV_LOG_WARN("Can't attach external user data and destructor callback to a NULL object");
|
||||
return;
|
||||
}
|
||||
|
||||
obj->ext_data.data = data;
|
||||
obj->ext_data.free_cb = free_cb;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
if(LV_USE_OBJ_NAME) {
|
||||
LV_ASSERT_NULL(class_p->name);
|
||||
}
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
obj->ext_data.free_cb = NULL;
|
||||
obj->ext_data.data = NULL;
|
||||
#endif
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
const lv_obj_class_t * original_class_p = obj->class_p;
|
||||
|
||||
/*Don't let the descendant methods run during constructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Construct the base first*/
|
||||
lv_obj_construct(class_p, obj);
|
||||
|
||||
/*Restore the original class*/
|
||||
obj->class_p = original_class_p;
|
||||
}
|
||||
|
||||
if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(class_p, obj);
|
||||
}
|
||||
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p)
|
||||
{
|
||||
/*Find a base in which instance size is set*/
|
||||
const lv_obj_class_t * base = class_p;
|
||||
while(base && base->instance_size == 0) base = base->base_class;
|
||||
|
||||
if(base == NULL) return 0; /*Never happens: set at least in `lv_obj` class*/
|
||||
|
||||
return base->instance_size;
|
||||
}
|
||||
89
inc/lvgl/src/core/lv_obj_class.h
Normal file
89
inc/lvgl/src/core/lv_obj_class.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file lv_obj_class.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_CLASS_H
|
||||
#define LV_OBJ_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "lv_obj_property.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
|
||||
LV_OBJ_CLASS_EDITABLE_TRUE,
|
||||
LV_OBJ_CLASS_EDITABLE_FALSE,
|
||||
} lv_obj_class_editable_t;
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_CLASS_GROUP_DEF_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
|
||||
LV_OBJ_CLASS_GROUP_DEF_TRUE,
|
||||
LV_OBJ_CLASS_GROUP_DEF_FALSE,
|
||||
} lv_obj_class_group_def_t;
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_CLASS_THEME_INHERITABLE_FALSE, /**< Do not inherit theme from base class. */
|
||||
LV_OBJ_CLASS_THEME_INHERITABLE_TRUE,
|
||||
} lv_obj_class_theme_inheritable_t;
|
||||
|
||||
typedef void (*lv_obj_class_event_cb_t)(lv_obj_class_t * class_p, lv_event_t * e);
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create an object form a class descriptor
|
||||
* @param class_p pointer to a class
|
||||
* @param parent pointer to an object where the new object should be created
|
||||
* @return pointer to the created object
|
||||
*/
|
||||
lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent);
|
||||
|
||||
void lv_obj_class_init_obj(lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_editable(lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_group_def(lv_obj_t * obj);
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
/**
|
||||
* @brief Associates an array of external data pointers with an LVGL object
|
||||
*
|
||||
* Associates custom user data with an LVGL object and specifies a destructor function
|
||||
* that will be automatically invoked when the object is deleted to properly clean up
|
||||
* the associated resources.
|
||||
*
|
||||
* @param obj Target LVGL object
|
||||
* @param data User-defined data pointer to associate with a object
|
||||
* @param free_cb Cleanup function called for each non-NULL data pointer during
|
||||
* object deletion. Receives single data pointer as parameter.
|
||||
* NULL means no automatic cleanup.
|
||||
*/
|
||||
void lv_obj_set_external_data(lv_obj_t * obj, void * data, void (* free_cb)(void * data));
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_CLASS_H*/
|
||||
78
inc/lvgl/src/core/lv_obj_class_private.h
Normal file
78
inc/lvgl/src/core/lv_obj_class_private.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_obj_class_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_CLASS_PRIVATE_H
|
||||
#define LV_OBJ_CLASS_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_obj_class.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Describe the common methods of every object.
|
||||
* Similar to a C++ class.
|
||||
*/
|
||||
struct _lv_obj_class_t {
|
||||
const lv_obj_class_t * base_class;
|
||||
/** class_p is the final class while obj->class_p is the class currently being [de]constructed. */
|
||||
void (*constructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
void (*destructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
|
||||
/** class_p is the class in which event is being processed. */
|
||||
void (*event_cb)(const lv_obj_class_t * class_p, lv_event_t * e); /**< Widget type specific event function*/
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
uint32_t prop_index_start;
|
||||
uint32_t prop_index_end;
|
||||
const lv_property_ops_t * properties;
|
||||
uint32_t properties_count;
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY_NAME
|
||||
/* An array of property ID and name */
|
||||
const lv_property_name_t * property_names;
|
||||
uint32_t names_count;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void * user_data;
|
||||
const char * name;
|
||||
int32_t width_def;
|
||||
int32_t height_def;
|
||||
uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/
|
||||
uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/
|
||||
uint32_t instance_size : 16;
|
||||
uint32_t theme_inheritable : 1; /**< Value from ::lv_obj_class_theme_inheritable_t*/
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_obj_destruct(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_CLASS_PRIVATE_H*/
|
||||
512
inc/lvgl/src/core/lv_obj_draw.c
Normal file
512
inc/lvgl/src/core/lv_obj_draw.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/**
|
||||
* @file lv_obj_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_draw_private.h"
|
||||
#include "lv_obj_private.h"
|
||||
#include "lv_obj_style.h"
|
||||
#include "../display/lv_display.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_obj_class)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static inline lv_opa_t get_layer_opa(const lv_obj_t * obj, lv_part_t part, const lv_draw_dsc_base_t * base_dsc);
|
||||
static lv_color_t normal_apply_layer_recolor(const lv_obj_t * obj, lv_part_t part, const lv_draw_dsc_base_t * base_dsc,
|
||||
lv_color_t color);
|
||||
static lv_color32_t image_apply_layer_recolor(const lv_obj_t * obj, lv_part_t part,
|
||||
const lv_draw_dsc_base_t * base_dsc, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
static void drop_shadow_init(const lv_obj_t * obj, lv_part_t part, lv_draw_dsc_base_t * base_dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
lv_opa_t opa = get_layer_opa(obj, part, &draw_dsc->base);
|
||||
if(part != LV_PART_MAIN) {
|
||||
if(opa <= LV_OPA_MIN) {
|
||||
draw_dsc->bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->bg_image_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;
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
lv_color_t bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
draw_dsc->bg_color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, bg_color);
|
||||
const lv_grad_dsc_t * grad = lv_obj_get_style_bg_grad(obj, part);
|
||||
if(grad && grad->dir != LV_GRAD_DIR_NONE) {
|
||||
lv_memcpy(&draw_dsc->bg_grad, grad, sizeof(*grad));
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_grad.dir = lv_obj_get_style_bg_grad_dir(obj, part);
|
||||
if(draw_dsc->bg_grad.dir != LV_GRAD_DIR_NONE) {
|
||||
draw_dsc->bg_grad.stops[0].color = draw_dsc->bg_color;
|
||||
lv_color_t bg_grad_color = lv_obj_get_style_bg_grad_color_filtered(obj, part);
|
||||
draw_dsc->bg_grad.stops[1].color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, bg_grad_color);
|
||||
draw_dsc->bg_grad.stops[0].frac = lv_obj_get_style_bg_main_stop(obj, part);
|
||||
draw_dsc->bg_grad.stops[1].frac = lv_obj_get_style_bg_grad_stop(obj, part);
|
||||
draw_dsc->bg_grad.stops[0].opa = lv_obj_get_style_bg_main_opa(obj, part);
|
||||
draw_dsc->bg_grad.stops[1].opa = lv_obj_get_style_bg_grad_opa(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
lv_color_t border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
draw_dsc->border_color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, border_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(draw_dsc->outline_opa > LV_OPA_MIN) {
|
||||
draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
lv_color_t outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
|
||||
draw_dsc->outline_color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, outline_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->bg_image_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_image_src = lv_obj_get_style_bg_image_src(obj, part);
|
||||
if(draw_dsc->bg_image_src) {
|
||||
draw_dsc->bg_image_opa = lv_obj_get_style_bg_image_opa(obj, part);
|
||||
if(draw_dsc->bg_image_opa > LV_OPA_MIN) {
|
||||
if(lv_image_src_get_type(draw_dsc->bg_image_src) == LV_IMAGE_SRC_SYMBOL) {
|
||||
draw_dsc->bg_image_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
lv_color_t text_color = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
draw_dsc->bg_image_recolor = normal_apply_layer_recolor(obj, part, &draw_dsc->base, text_color);
|
||||
}
|
||||
else {
|
||||
lv_color_t bg_image_recolor = lv_obj_get_style_bg_image_recolor_filtered(obj, part);
|
||||
lv_opa_t bg_image_recolor_opa = lv_obj_get_style_bg_image_recolor_opa(obj, part);
|
||||
lv_color32_t result = image_apply_layer_recolor(obj, part, &draw_dsc->base, bg_image_recolor, bg_image_recolor_opa);
|
||||
draw_dsc->bg_image_recolor_opa = result.alpha;
|
||||
draw_dsc->bg_image_recolor = lv_color_make(result.red, result.green, result.blue);
|
||||
draw_dsc->bg_image_tiled = lv_obj_get_style_bg_image_tiled(obj, part);
|
||||
}
|
||||
|
||||
draw_dsc->bg_image_colorkey = lv_obj_get_style_image_colorkey(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->shadow_opa) {
|
||||
draw_dsc->shadow_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(draw_dsc->shadow_width) {
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_offset_x = lv_obj_get_style_shadow_offset_x(obj, part);
|
||||
draw_dsc->shadow_offset_y = lv_obj_get_style_shadow_offset_y(obj, part);
|
||||
draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part);
|
||||
lv_color_t shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part);
|
||||
draw_dsc->shadow_color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, shadow_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->bg_opa = LV_OPA_MIX2(draw_dsc->bg_opa, opa);
|
||||
draw_dsc->bg_image_opa = LV_OPA_MIX2(draw_dsc->bg_image_opa, opa);
|
||||
draw_dsc->border_opa = LV_OPA_MIX2(draw_dsc->border_opa, opa);
|
||||
draw_dsc->shadow_opa = LV_OPA_MIX2(draw_dsc->shadow_opa, opa);
|
||||
draw_dsc->outline_opa = LV_OPA_MIX2(draw_dsc->outline_opa, opa);
|
||||
}
|
||||
|
||||
drop_shadow_init(obj, part, &draw_dsc->base);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_label_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_text_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_opa_t opa = get_layer_opa(obj, part, &draw_dsc->base);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
lv_color_t text_color = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
draw_dsc->color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, text_color);
|
||||
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);
|
||||
|
||||
draw_dsc->font = lv_obj_get_style_text_font(obj, part);
|
||||
|
||||
#if LV_USE_BIDI
|
||||
draw_dsc->bidi_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||
#endif
|
||||
|
||||
draw_dsc->align = lv_obj_get_style_text_align(obj, part);
|
||||
|
||||
drop_shadow_init(obj, part, &draw_dsc->base);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_image_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_image_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_image_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_opa_t opa = get_layer_opa(obj, part, &draw_dsc->base);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_dsc->rotation = 0;
|
||||
draw_dsc->scale_x = LV_SCALE_NONE;
|
||||
draw_dsc->scale_y = LV_SCALE_NONE;
|
||||
draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2;
|
||||
draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2;
|
||||
|
||||
lv_color_t recolor = lv_obj_get_style_image_recolor_filtered(obj, part);
|
||||
lv_opa_t recolor_opa = lv_obj_get_style_image_recolor_opa(obj, part);
|
||||
lv_color32_t result = image_apply_layer_recolor(obj, part, &draw_dsc->base, recolor, recolor_opa);
|
||||
draw_dsc->recolor_opa = result.alpha;
|
||||
draw_dsc->recolor = lv_color_make(result.red, result.green, result.blue);
|
||||
|
||||
draw_dsc->colorkey = lv_obj_get_style_image_colorkey(obj, part);
|
||||
|
||||
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
|
||||
drop_shadow_init(obj, part, &draw_dsc->base);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_line_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_line_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_opa_t opa = get_layer_opa(obj, part, &draw_dsc->base);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_dsc->width = lv_obj_get_style_line_width(obj, part);
|
||||
if(draw_dsc->width == 0) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color_t line_color = lv_obj_get_style_line_color_filtered(obj, part);
|
||||
draw_dsc->color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, line_color);
|
||||
|
||||
draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part);
|
||||
if(draw_dsc->dash_width) {
|
||||
draw_dsc->dash_gap = lv_obj_get_style_line_dash_gap(obj, part);
|
||||
}
|
||||
|
||||
draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part);
|
||||
draw_dsc->round_end = draw_dsc->round_start;
|
||||
|
||||
drop_shadow_init(obj, part, &draw_dsc->base);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_arc_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
draw_dsc->width = lv_obj_get_style_arc_width(obj, part);
|
||||
if(draw_dsc->width == 0) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_opa_t opa = get_layer_opa(obj, part, &draw_dsc->base);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) {
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color_t arc_color = lv_obj_get_style_arc_color_filtered(obj, part);
|
||||
draw_dsc->color = normal_apply_layer_recolor(obj, part, &draw_dsc->base, arc_color);
|
||||
draw_dsc->img_src = lv_obj_get_style_arc_image_src(obj, part);
|
||||
|
||||
draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
|
||||
|
||||
drop_shadow_init(obj, part, &draw_dsc->base);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_blur_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_blur_dsc_t * draw_dsc)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
draw_dsc->base.obj = obj;
|
||||
draw_dsc->base.part = part;
|
||||
|
||||
draw_dsc->blur_radius = lv_obj_get_style_blur_radius(obj, part);
|
||||
draw_dsc->quality = lv_obj_get_style_blur_quality(obj, part);
|
||||
|
||||
/*Radius might be set earlier as it's already known*/
|
||||
if(draw_dsc->corner_radius == 0) {
|
||||
draw_dsc->corner_radius = lv_obj_get_style_radius(obj, part);
|
||||
}
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
|
||||
int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
int32_t s = 0;
|
||||
|
||||
int32_t sh_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(sh_width) {
|
||||
lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(sh_opa > LV_OPA_MIN) {
|
||||
sh_width = sh_width / 2 + 1; /*The blur adds only half width*/
|
||||
sh_width += lv_obj_get_style_shadow_spread(obj, part);
|
||||
int32_t sh_ofs_x = lv_obj_get_style_shadow_offset_x(obj, part);
|
||||
int32_t sh_ofs_y = lv_obj_get_style_shadow_offset_y(obj, part);
|
||||
sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y));
|
||||
s = LV_MAX(s, sh_width);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(outline_width) {
|
||||
lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(outline_opa > LV_OPA_MIN) {
|
||||
int32_t outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
s = LV_MAX(s, outline_pad + outline_width);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t drop_shadow_size = 0;
|
||||
if(lv_obj_get_style_drop_shadow_opa(obj, part) > 0) {
|
||||
drop_shadow_size += LV_MAX(LV_ABS(lv_obj_get_style_drop_shadow_offset_x(obj, part)),
|
||||
LV_ABS(lv_obj_get_style_drop_shadow_offset_y(obj, part)));
|
||||
|
||||
drop_shadow_size += lv_obj_get_style_drop_shadow_radius(obj, part) + 1;
|
||||
}
|
||||
s += drop_shadow_size;
|
||||
|
||||
int32_t w = lv_obj_get_style_transform_width(obj, part);
|
||||
int32_t h = lv_obj_get_style_transform_height(obj, part);
|
||||
int32_t wh = LV_MAX(w, h);
|
||||
if(wh > 0) s += wh;
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
return s;
|
||||
}
|
||||
|
||||
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
int32_t s_old = lv_obj_get_ext_draw_size(obj);
|
||||
int32_t s_new = 0;
|
||||
lv_obj_send_event(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new);
|
||||
|
||||
/*Store the result if the special attrs already allocated*/
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
/*Allocate spec. attrs. only if the result is not zero.
|
||||
*Zero is the default value if the spec. attr. are not defined.*/
|
||||
else if(s_new != 0) {
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_ext_draw_size(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->ext_draw_size;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
lv_layer_type_t lv_obj_get_layer_type(const lv_obj_t * obj)
|
||||
{
|
||||
|
||||
if(obj->spec_attr) return (lv_layer_type_t)obj->spec_attr->layer_type;
|
||||
else return LV_LAYER_TYPE_NONE;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline lv_opa_t get_layer_opa(const lv_obj_t * obj, lv_part_t part, const lv_draw_dsc_base_t * base_dsc)
|
||||
{
|
||||
if(base_dsc->layer) {
|
||||
/* Accessing the layer opa directly is faster than using get style opa recursive */
|
||||
if(part == LV_PART_MAIN) {
|
||||
return base_dsc->layer->opa;
|
||||
}
|
||||
|
||||
return LV_OPA_MIX2(base_dsc->layer->opa, lv_obj_get_style_opa(obj, part));
|
||||
}
|
||||
|
||||
/* fallback to old recursive style opa */
|
||||
return lv_obj_get_style_opa_recursive(obj, part);
|
||||
}
|
||||
|
||||
|
||||
static lv_color_t normal_apply_layer_recolor(const lv_obj_t * obj, lv_part_t part, const lv_draw_dsc_base_t * base_dsc,
|
||||
lv_color_t color)
|
||||
{
|
||||
lv_color32_t recolor;
|
||||
|
||||
if(base_dsc->layer) {
|
||||
recolor = base_dsc->layer->recolor;
|
||||
if(part != LV_PART_MAIN) {
|
||||
recolor = lv_obj_style_apply_recolor(obj, part, recolor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
recolor = lv_obj_get_style_recolor_recursive(obj, part);
|
||||
}
|
||||
|
||||
return lv_color_mix(lv_color_make(recolor.red, recolor.green, recolor.blue), color, recolor.alpha);
|
||||
}
|
||||
|
||||
|
||||
static lv_color32_t image_apply_layer_recolor(const lv_obj_t * obj, lv_part_t part,
|
||||
const lv_draw_dsc_base_t * base_dsc, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
lv_color32_t recolor;
|
||||
|
||||
if(base_dsc->layer) {
|
||||
recolor = base_dsc->layer->recolor;
|
||||
if(part != LV_PART_MAIN) {
|
||||
recolor = lv_obj_style_apply_recolor(obj, part, recolor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
recolor = lv_obj_get_style_recolor_recursive(obj, part);
|
||||
}
|
||||
|
||||
if(opa > LV_OPA_TRANSP && recolor.alpha > LV_OPA_TRANSP) {
|
||||
return lv_color_over32(recolor, lv_color_to_32(color, opa));
|
||||
}
|
||||
else if(recolor.alpha > LV_OPA_TRANSP) {
|
||||
return recolor;
|
||||
}
|
||||
else {
|
||||
return lv_color_to_32(color, opa);
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_shadow_init(const lv_obj_t * obj, lv_part_t part, lv_draw_dsc_base_t * base_dsc)
|
||||
{
|
||||
base_dsc->drop_shadow_opa = lv_obj_get_style_drop_shadow_opa(obj, part);
|
||||
if(base_dsc->drop_shadow_opa) {
|
||||
base_dsc->drop_shadow_blur_radius = lv_obj_get_style_drop_shadow_radius(obj, part);
|
||||
base_dsc->drop_shadow_ofs_x = lv_obj_get_style_drop_shadow_offset_x(obj, part);
|
||||
base_dsc->drop_shadow_ofs_y = lv_obj_get_style_drop_shadow_offset_y(obj, part);
|
||||
base_dsc->drop_shadow_color = lv_obj_get_style_drop_shadow_color(obj, part);
|
||||
base_dsc->drop_shadow_color = normal_apply_layer_recolor(obj, part, base_dsc, base_dsc->drop_shadow_color);
|
||||
|
||||
base_dsc->drop_shadow_quality = lv_obj_get_style_drop_shadow_quality(obj, part);
|
||||
}
|
||||
}
|
||||
142
inc/lvgl/src/core/lv_obj_draw.h
Normal file
142
inc/lvgl/src/core/lv_obj_draw.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @file lv_obj_draw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_DRAW_H
|
||||
#define LV_OBJ_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../draw/lv_draw_rect.h"
|
||||
#include "../draw/lv_draw_label.h"
|
||||
#include "../draw/lv_draw_image.h"
|
||||
#include "../draw/lv_draw_line.h"
|
||||
#include "../draw/lv_draw_arc.h"
|
||||
#include "../draw/lv_draw_triangle.h"
|
||||
#include "../draw/lv_draw_blur.h"
|
||||
#include "lv_obj_style.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Store the type of layer required to render a widget.*/
|
||||
typedef enum {
|
||||
/**No layer is needed. */
|
||||
LV_LAYER_TYPE_NONE,
|
||||
|
||||
/**Simple layer means that the layer can be rendered in chunks.
|
||||
* For example with opa_layered = 140 it's possible to render only 10 lines
|
||||
* from the layer. When it's ready go to the next 10 lines.
|
||||
* It avoids large memory allocations for the layer buffer.
|
||||
* The buffer size for a chunk can be set by `LV_DRAW_LAYER_SIMPLE_BUF_SIZE` in lv_conf.h.*/
|
||||
LV_LAYER_TYPE_SIMPLE,
|
||||
|
||||
/**The widget is transformed and cannot be rendered in chunks.
|
||||
* It's because - due to the transformations - pixel outside of
|
||||
* a given area will also contribute to the final image.
|
||||
* In this case there is no limitation on the buffer size.
|
||||
* LVGL will allocate as large buffer as needed to render the transformed area.*/
|
||||
LV_LAYER_TYPE_TRANSFORM,
|
||||
} lv_layer_type_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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)`.
|
||||
* @note Only the relevant fields will be set.
|
||||
* E.g. if `border width == 0` the other border properties won't be evaluated.
|
||||
*/
|
||||
void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_rect_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* 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)`.
|
||||
*/
|
||||
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, lv_part_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)`.
|
||||
*/
|
||||
void lv_obj_init_draw_image_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_image_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* 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)`.
|
||||
*/
|
||||
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, lv_part_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)`.
|
||||
*/
|
||||
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_arc_dsc_t * draw_dsc);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a blur draw descriptor from an object's styles in its current state.
|
||||
* draw_dsc->radius will only be calculated if it's 0 initially. Radius can be set before calling this function
|
||||
* to avoid getting it twice.
|
||||
* @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_blur_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_blur_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_blur_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
|
||||
*/
|
||||
int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, lv_part_t part);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_DRAW_H*/
|
||||
48
inc/lvgl/src/core/lv_obj_draw_private.h
Normal file
48
inc/lvgl/src/core/lv_obj_draw_private.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file lv_obj_draw_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_DRAW_PRIVATE_H
|
||||
#define LV_OBJ_DRAW_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_obj_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the extended draw area of an object.
|
||||
* @param obj pointer to an object
|
||||
* @return the size extended draw area around the real coordinates
|
||||
*/
|
||||
int32_t lv_obj_get_ext_draw_size(const lv_obj_t * obj);
|
||||
|
||||
lv_layer_type_t lv_obj_get_layer_type(const lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_DRAW_PRIVATE_H*/
|
||||
491
inc/lvgl/src/core/lv_obj_event.c
Normal file
491
inc/lvgl/src/core/lv_obj_event.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/**
|
||||
* @file lv_obj_event.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_event_private.h"
|
||||
#include "lv_obj_event_private.h"
|
||||
#include "lv_obj_class_private.h"
|
||||
#include "lv_obj_private.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "../indev/lv_indev_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_obj_class)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_result_t event_send_core(lv_event_t * e);
|
||||
static bool event_is_bubbled(lv_event_t * e);
|
||||
static bool event_is_trickled(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_EVENT
|
||||
#define LV_TRACE_EVENT(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define LV_TRACE_EVENT(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param)
|
||||
{
|
||||
if(obj == NULL) return LV_RESULT_OK;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_event_t e;
|
||||
e.current_target = obj;
|
||||
e.original_target = obj;
|
||||
e.code = event_code;
|
||||
e.user_data = NULL;
|
||||
e.param = param;
|
||||
e.deleted = 0;
|
||||
e.stop_bubbling = 0;
|
||||
e.stop_processing = 0;
|
||||
e.stop_trickling = 0;
|
||||
|
||||
lv_event_push(&e);
|
||||
|
||||
/*Send the event*/
|
||||
lv_result_t res = event_send_core(&e);
|
||||
|
||||
/*Remove this element from the list*/
|
||||
lv_event_pop(&e);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
const lv_obj_class_t * base;
|
||||
if(class_p == NULL) base = ((lv_obj_t *)e->current_target)->class_p;
|
||||
else base = class_p->base_class;
|
||||
|
||||
/*Find a base in which call the ancestor's event handler_cb if set*/
|
||||
while(base && base->event_cb == NULL) base = base->base_class;
|
||||
|
||||
if(base == NULL) return LV_RESULT_OK;
|
||||
if(base->event_cb == NULL) return LV_RESULT_OK;
|
||||
|
||||
/*Call the actual event callback*/
|
||||
e->user_data = NULL;
|
||||
LV_PROFILER_EVENT_BEGIN_TAG(lv_event_code_get_name(e->code));
|
||||
base->event_cb(base, e);
|
||||
LV_PROFILER_EVENT_END_TAG(lv_event_code_get_name(e->code));
|
||||
|
||||
lv_result_t res = LV_RESULT_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) res = LV_RESULT_INVALID;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
return lv_event_add(&obj->spec_attr->event_list, event_cb, filter, user_data);
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_event_count(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return lv_event_get_count(&obj->spec_attr->event_list);
|
||||
}
|
||||
|
||||
lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
return lv_event_get_dsc(&obj->spec_attr->event_list, index);
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
return lv_event_remove(&obj->spec_attr->event_list, index);
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_dsc(lv_obj_t * obj, lv_event_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_NULL(dsc);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
return lv_event_remove_dsc(&obj->spec_attr->event_list, dsc);
|
||||
}
|
||||
|
||||
uint32_t lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
|
||||
uint32_t event_cnt = lv_obj_get_event_count(obj);
|
||||
uint32_t removed_count = 0;
|
||||
int32_t i;
|
||||
|
||||
if(event_cnt == 0) return 0;
|
||||
|
||||
for(i = event_cnt - 1; i >= 0; i--) {
|
||||
lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i);
|
||||
if(dsc && dsc->cb == event_cb) {
|
||||
lv_obj_remove_event(obj, i);
|
||||
removed_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return removed_count;
|
||||
}
|
||||
|
||||
uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
|
||||
uint32_t event_cnt = lv_obj_get_event_count(obj);
|
||||
uint32_t removed_count = 0;
|
||||
int32_t i;
|
||||
|
||||
if(event_cnt == 0) return 0;
|
||||
|
||||
for(i = event_cnt - 1; i >= 0; i--) {
|
||||
lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i);
|
||||
if(dsc && (event_cb == NULL || dsc->cb == event_cb) && dsc->user_data == user_data) {
|
||||
lv_obj_remove_event(obj, i);
|
||||
removed_count ++;
|
||||
}
|
||||
}
|
||||
|
||||
return removed_count;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e)
|
||||
{
|
||||
return lv_event_get_current_target(e);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_event_get_target_obj(lv_event_t * e)
|
||||
{
|
||||
return lv_event_get_target(e);
|
||||
}
|
||||
|
||||
lv_indev_t * lv_event_get_indev(lv_event_t * e)
|
||||
{
|
||||
|
||||
if(e->code == LV_EVENT_PRESSED ||
|
||||
e->code == LV_EVENT_PRESSING ||
|
||||
e->code == LV_EVENT_PRESS_LOST ||
|
||||
e->code == LV_EVENT_SHORT_CLICKED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED_REPEAT ||
|
||||
e->code == LV_EVENT_CLICKED ||
|
||||
e->code == LV_EVENT_RELEASED ||
|
||||
e->code == LV_EVENT_SCROLL_BEGIN ||
|
||||
e->code == LV_EVENT_SCROLL_END ||
|
||||
e->code == LV_EVENT_SCROLL ||
|
||||
e->code == LV_EVENT_GESTURE ||
|
||||
e->code == LV_EVENT_KEY ||
|
||||
e->code == LV_EVENT_FOCUSED ||
|
||||
e->code == LV_EVENT_DEFOCUSED ||
|
||||
e->code == LV_EVENT_LEAVE ||
|
||||
e->code == LV_EVENT_HOVER_OVER ||
|
||||
e->code == LV_EVENT_HOVER_LEAVE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_layer_t * lv_event_get_layer(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_MAIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_END ||
|
||||
e->code == LV_EVENT_DRAW_POST ||
|
||||
e->code == LV_EVENT_DRAW_POST_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_POST_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_old_size(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SIZE_CHANGED) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_event_get_key(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_KEY) {
|
||||
uint32_t * k = lv_event_get_param(e);
|
||||
if(k) return *k;
|
||||
else return 0;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t lv_event_get_rotary_diff(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_ROTARY) {
|
||||
int32_t * r = lv_event_get_param(e);
|
||||
if(r) return *r;
|
||||
else return 0;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SCROLL_BEGIN) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size)
|
||||
{
|
||||
if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
int32_t * cur_size = lv_event_get_param(e);
|
||||
*cur_size = LV_MAX(*cur_size, size);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
lv_point_t * lv_event_get_self_size_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_GET_SELF_SIZE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_HIT_TEST) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
return p->area;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
if(res > p->res) p->res = res; /*Save only "stronger" results*/
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_TASK_ADDED) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_state_t lv_event_get_prev_state(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_STATE_CHANGED) {
|
||||
lv_state_t * state = lv_event_get_param(e);
|
||||
return state ? *state : 0;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_result_t event_send_core(lv_event_t * e)
|
||||
{
|
||||
LV_TRACE_EVENT("Sending event %d to %p with %p param", e->code, (void *)e->original_target, e->param);
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_active();
|
||||
if(indev_act) {
|
||||
if(e->stop_processing) return LV_RESULT_OK;
|
||||
if(e->deleted) return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_obj_t * target = e->current_target;
|
||||
lv_result_t res = LV_RESULT_OK;
|
||||
lv_event_list_t * list = target->spec_attr ? &target->spec_attr->event_list : NULL;
|
||||
|
||||
res = lv_event_send(list, e, true);
|
||||
if(res != LV_RESULT_OK || e->stop_processing) return res;
|
||||
|
||||
res = lv_obj_event_base(NULL, e);
|
||||
if(res != LV_RESULT_OK || e->stop_processing) return res;
|
||||
|
||||
res = lv_event_send(list, e, false);
|
||||
if(res != LV_RESULT_OK || e->stop_processing) return res;
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(e->current_target);
|
||||
if(parent && event_is_bubbled(e)) {
|
||||
e->current_target = parent;
|
||||
res = event_send_core(e);
|
||||
}
|
||||
if(res != LV_RESULT_OK) return res;
|
||||
|
||||
/*Trickle down to children if enabled*/
|
||||
if(event_is_trickled(e)) {
|
||||
uint32_t child_count = lv_obj_get_child_count(target);
|
||||
|
||||
/* we don't want the event to bubble up again when trickling down */
|
||||
e->stop_bubbling = 1;
|
||||
|
||||
for(uint32_t i = 0; i < child_count && res == LV_RESULT_OK && !e->stop_processing; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(target, i);
|
||||
if(child) {
|
||||
e->current_target = child;
|
||||
res = event_send_core(e);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_WARN("Trickle down event %d to child %p failed", e->code, (void *)child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool event_is_bubbled(lv_event_t * e)
|
||||
{
|
||||
if(e->stop_bubbling) return false;
|
||||
|
||||
/*Event codes that always bubble*/
|
||||
switch(e->code) {
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*Check other codes only if bubbling is enabled*/
|
||||
if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false;
|
||||
|
||||
switch(e->code) {
|
||||
case LV_EVENT_HIT_TEST:
|
||||
case LV_EVENT_COVER_CHECK:
|
||||
case LV_EVENT_REFR_EXT_DRAW_SIZE:
|
||||
case LV_EVENT_DRAW_MAIN_BEGIN:
|
||||
case LV_EVENT_DRAW_MAIN:
|
||||
case LV_EVENT_DRAW_MAIN_END:
|
||||
case LV_EVENT_DRAW_POST_BEGIN:
|
||||
case LV_EVENT_DRAW_POST:
|
||||
case LV_EVENT_DRAW_POST_END:
|
||||
case LV_EVENT_DRAW_TASK_ADDED:
|
||||
case LV_EVENT_REFRESH:
|
||||
case LV_EVENT_DELETE:
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
case LV_EVENT_CHILD_CHANGED:
|
||||
case LV_EVENT_SIZE_CHANGED:
|
||||
case LV_EVENT_STYLE_CHANGED:
|
||||
case LV_EVENT_GET_SELF_SIZE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool event_is_trickled(lv_event_t * e)
|
||||
{
|
||||
if(e->stop_trickling) return false;
|
||||
|
||||
/*Check other codes only if trickle is enabled*/
|
||||
if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_TRICKLE) == false) return false;
|
||||
|
||||
switch(e->code) {
|
||||
case LV_EVENT_HIT_TEST:
|
||||
case LV_EVENT_COVER_CHECK:
|
||||
case LV_EVENT_REFR_EXT_DRAW_SIZE:
|
||||
case LV_EVENT_DRAW_MAIN_BEGIN:
|
||||
case LV_EVENT_DRAW_MAIN:
|
||||
case LV_EVENT_DRAW_MAIN_END:
|
||||
case LV_EVENT_DRAW_POST_BEGIN:
|
||||
case LV_EVENT_DRAW_POST:
|
||||
case LV_EVENT_DRAW_POST_END:
|
||||
case LV_EVENT_DRAW_TASK_ADDED:
|
||||
case LV_EVENT_REFRESH:
|
||||
case LV_EVENT_DELETE:
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
case LV_EVENT_CHILD_CHANGED:
|
||||
case LV_EVENT_SIZE_CHANGED:
|
||||
case LV_EVENT_STYLE_CHANGED:
|
||||
case LV_EVENT_GET_SELF_SIZE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
213
inc/lvgl/src/core/lv_obj_event.h
Normal file
213
inc/lvgl/src/core/lv_obj_event.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @file lv_obj_event.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_EVENT_H
|
||||
#define LV_OBJ_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_event.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "lv_obj_style.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Cover check results.*/
|
||||
typedef enum {
|
||||
LV_COVER_RES_COVER = 0,
|
||||
LV_COVER_RES_NOT_COVER = 1,
|
||||
LV_COVER_RES_MASKED = 2,
|
||||
} lv_cover_res_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Send an event to the object
|
||||
* @param obj pointer to an object
|
||||
* @param event_code the type of the event from `lv_event_t`
|
||||
* @param param arbitrary data depending on the widget type and the event. (Usually `NULL`)
|
||||
* @return LV_RESULT_OK: `obj` was not deleted in the event; LV_RESULT_INVALID: `obj` was deleted in the event_code
|
||||
*/
|
||||
lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param);
|
||||
|
||||
/**
|
||||
* Used by the widgets internally to call the ancestor widget types's event handler
|
||||
* @param class_p pointer to the class of the widget (NOT the ancestor class)
|
||||
* @param e pointer to the event descriptor
|
||||
* @return LV_RESULT_OK: the target object was not deleted in the event; LV_RESULT_INVALID: it was deleted in the event_code
|
||||
*/
|
||||
lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the current target of the event. It's the object which event handler being called.
|
||||
* If the event is not bubbled it's the same as "original" target.
|
||||
* @param e pointer to the event descriptor
|
||||
* @return the target of the event_code
|
||||
*/
|
||||
lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the object originally targeted by the event. It's the same even if the event is bubbled.
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the original target of the event_code
|
||||
*/
|
||||
lv_obj_t * lv_event_get_target_obj(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Add an event handler function for an object.
|
||||
* Used by the user to react on event which happens with the object.
|
||||
* An object can have multiple event handler. They will be called in the same order as they were added.
|
||||
* @param obj pointer to an object
|
||||
* @param filter an event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be used to receive all the events.
|
||||
* @param event_cb the new event function
|
||||
* @param user_data custom data will be available in `event_cb`
|
||||
* @return handler to the event. It can be used in `lv_obj_remove_event_dsc`.
|
||||
*/
|
||||
lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data);
|
||||
|
||||
uint32_t lv_obj_get_event_count(lv_obj_t * obj);
|
||||
|
||||
lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index);
|
||||
|
||||
bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index);
|
||||
|
||||
bool lv_obj_remove_event_dsc(lv_obj_t * obj, lv_event_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Remove an event_cb from an object
|
||||
* @param obj pointer to a obj
|
||||
* @param event_cb the event_cb of the event to remove
|
||||
* @return the count of the event removed
|
||||
*/
|
||||
uint32_t lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb);
|
||||
|
||||
/**
|
||||
* Remove an event_cb with user_data
|
||||
* @param obj pointer to a obj
|
||||
* @param event_cb the event_cb of the event to remove
|
||||
* @param user_data user_data
|
||||
* @return the count of the event removed
|
||||
*/
|
||||
uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Get the input device passed as parameter to indev related events.
|
||||
* @param e pointer to an event
|
||||
* @return the indev that triggered the event or NULL if called on a not indev related event
|
||||
*/
|
||||
lv_indev_t * lv_event_get_indev(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the draw context which should be the first parameter of the draw functions.
|
||||
* Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to a draw context or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_layer_t * lv_event_get_layer(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED`
|
||||
* @param e pointer to an event
|
||||
* @return the old absolute area of the object or NULL if called on an unrelated event
|
||||
*/
|
||||
const lv_area_t * lv_event_get_old_size(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY`
|
||||
* @param e pointer to an event
|
||||
* @return the triggering key or NULL if called on an unrelated event
|
||||
*/
|
||||
uint32_t lv_event_get_key(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the signed rotary encoder diff. passed as parameter to an event. Can be used in `LV_EVENT_ROTARY`
|
||||
* @param e pointer to an event
|
||||
* @return the triggering key or NULL if called on an unrelated event
|
||||
*/
|
||||
int32_t lv_event_get_rotary_diff(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN`
|
||||
* @param e pointer to an event
|
||||
* @return the animation that will scroll the object. (can be modified as required)
|
||||
*/
|
||||
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE`
|
||||
* @param e pointer to an event
|
||||
* @param size The new extra draw size
|
||||
*/
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size);
|
||||
|
||||
/**
|
||||
* Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`).
|
||||
* Can be used in `LV_EVENT_GET_SELF_SIZE`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to `lv_point_t` or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_point_t * lv_event_get_self_size_info(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get a pointer to an area which should be examined whether the object fully covers it or not.
|
||||
* Can be used in `LV_EVENT_HIT_TEST`
|
||||
* @param e pointer to an event
|
||||
* @return an area with absolute coordinates to check
|
||||
*/
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK`
|
||||
* @param e pointer to an event
|
||||
* @param res an element of ::lv_cover_check_info_t
|
||||
*/
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res);
|
||||
|
||||
/**
|
||||
* Get the draw task which was just added.
|
||||
* Can be used in `LV_EVENT_DRAW_TASK_ADDED event`
|
||||
* @param e pointer to an event
|
||||
* @return the added draw task
|
||||
*/
|
||||
lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the previous state before the state change.
|
||||
* Can be used in `LV_EVENT_STATE_CHANGED` event
|
||||
* @param e pointer to an event
|
||||
* @return the previous state
|
||||
*/
|
||||
lv_state_t lv_event_get_prev_state(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_EVENT_H*/
|
||||
62
inc/lvgl/src/core/lv_obj_event_private.h
Normal file
62
inc/lvgl/src/core/lv_obj_event_private.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file lv_obj_event_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_EVENT_PRIVATE_H
|
||||
#define LV_OBJ_EVENT_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_obj_event.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not.
|
||||
* `res` should be set like this:
|
||||
* - If already set to `false` another event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it.
|
||||
* - If already set `true` and `point` shouldn't be clickable set to `false`
|
||||
* - If already set to `true` you agree that `point` can click the object leave it as `true`
|
||||
*/
|
||||
struct _lv_hit_test_info_t {
|
||||
const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/
|
||||
bool res; /**< true: `point` can click the object; false: it cannot*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not.
|
||||
* In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check
|
||||
* and `lv_event_set_cover_res(e, res)` to set the result.
|
||||
*/
|
||||
struct _lv_cover_check_info_t {
|
||||
lv_cover_res_t res;
|
||||
const lv_area_t * area;
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_EVENT_PRIVATE_H*/
|
||||
120
inc/lvgl/src/core/lv_obj_id_builtin.c
Normal file
120
inc/lvgl/src/core/lv_obj_id_builtin.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file lv_obj_id_builtin.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_class_private.h"
|
||||
#include "lv_obj_private.h"
|
||||
#include "lv_global.h"
|
||||
#include "../osal/lv_os_private.h"
|
||||
#include "../stdlib/lv_sprintf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
typedef struct _class_info_t {
|
||||
const lv_obj_class_t * class_p;
|
||||
uint32_t obj_count;
|
||||
} class_info_t;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OBJ_ID && LV_USE_OBJ_ID_BUILTIN
|
||||
|
||||
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT(obj && class_p);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t id = 0;
|
||||
lv_global_t * global = LV_GLOBAL_DEFAULT();
|
||||
class_info_t * info = NULL;
|
||||
|
||||
if(obj == NULL || class_p == NULL) return;
|
||||
if(global == NULL) return;
|
||||
|
||||
obj->id = NULL;
|
||||
|
||||
for(i = 0; i < global->objid_count; i ++) {
|
||||
info = ((class_info_t *)global->objid_array) + i;
|
||||
if(class_p == info->class_p) break;
|
||||
}
|
||||
|
||||
/*Resize array*/
|
||||
if(i == global->objid_count) {
|
||||
void * array = lv_realloc(global->objid_array, sizeof(class_info_t) * (global->objid_count + 1));
|
||||
LV_ASSERT_MALLOC(array);
|
||||
if(array == NULL) return;
|
||||
global->objid_array = array;
|
||||
global->objid_count ++;
|
||||
info = ((class_info_t *)global->objid_array) + i;
|
||||
info->obj_count = 0;
|
||||
info->class_p = class_p;
|
||||
}
|
||||
|
||||
id = ++info->obj_count;
|
||||
|
||||
obj->id = (void *)(lv_uintptr_t)id;
|
||||
}
|
||||
|
||||
void lv_obj_set_id(lv_obj_t * obj, void * id)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
if(obj->id) lv_obj_free_id(obj);
|
||||
obj->id = id;
|
||||
}
|
||||
|
||||
void lv_obj_free_id(lv_obj_t * obj)
|
||||
{
|
||||
obj->id = NULL;
|
||||
}
|
||||
|
||||
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len)
|
||||
{
|
||||
if(obj == NULL || obj->class_p == NULL) return NULL;
|
||||
if(buf == NULL) return NULL;
|
||||
|
||||
const char * name = obj->class_p->name;
|
||||
if(name == NULL) name = "nameless";
|
||||
|
||||
lv_snprintf(buf, len, "%s%" LV_PRIu32 "", name, (uint32_t)(lv_uintptr_t)obj->id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void lv_objid_builtin_destroy(void)
|
||||
{
|
||||
lv_global_t * global = LV_GLOBAL_DEFAULT();
|
||||
if(global == NULL) return;
|
||||
|
||||
lv_free(global->objid_array);
|
||||
global->objid_count = 0;
|
||||
}
|
||||
|
||||
int lv_obj_id_compare(const void * id1, const void * id2)
|
||||
{
|
||||
return id1 == id2 ? 0 : 1;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OBJ_ID_BUILTIN*/
|
||||
1634
inc/lvgl/src/core/lv_obj_pos.c
Normal file
1634
inc/lvgl/src/core/lv_obj_pos.c
Normal file
File diff suppressed because it is too large
Load Diff
567
inc/lvgl/src/core/lv_obj_pos.h
Normal file
567
inc/lvgl/src/core/lv_obj_pos.h
Normal file
@@ -0,0 +1,567 @@
|
||||
/**
|
||||
* @file lv_obj_pos.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_POS_H
|
||||
#define LV_OBJ_POS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
/** No flags */
|
||||
LV_OBJ_POINT_TRANSFORM_FLAG_NONE = 0x00,
|
||||
|
||||
/** Consider the transformation properties of the parents too */
|
||||
LV_OBJ_POINT_TRANSFORM_FLAG_RECURSIVE = 0x01,
|
||||
|
||||
/** Execute the inverse of the transformation (-angle and 1/zoom) */
|
||||
LV_OBJ_POINT_TRANSFORM_FLAG_INVERSE = 0x02,
|
||||
|
||||
/** Both inverse and recursive*/
|
||||
LV_OBJ_POINT_TRANSFORM_FLAG_INVERSE_RECURSIVE = 0x03,
|
||||
} lv_obj_point_transform_flag_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Set the position of an object relative to the set alignment.
|
||||
* @param obj pointer to an object
|
||||
* @param x new x coordinate
|
||||
* @param y new y coordinate
|
||||
* @note With default alignment it's the distance from the top left corner
|
||||
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
|
||||
* @note The position is interpreted on the content area of the parent
|
||||
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
|
||||
*/
|
||||
void lv_obj_set_pos(lv_obj_t * obj, int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Set the x coordinate of an object
|
||||
* @param obj pointer to an object
|
||||
* @param x new x coordinate
|
||||
* @note With default alignment it's the distance from the top left corner
|
||||
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
|
||||
* @note The position is interpreted on the content area of the parent
|
||||
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
|
||||
*/
|
||||
void lv_obj_set_x(lv_obj_t * obj, int32_t x);
|
||||
|
||||
/**
|
||||
* Set the y coordinate of an object
|
||||
* @param obj pointer to an object
|
||||
* @param y new y coordinate
|
||||
* @note With default alignment it's the distance from the top left corner
|
||||
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
|
||||
* @note The position is interpreted on the content area of the parent
|
||||
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
|
||||
*/
|
||||
void lv_obj_set_y(lv_obj_t * obj, int32_t y);
|
||||
|
||||
/**
|
||||
* Set the size of an object.
|
||||
* @param obj pointer to an object
|
||||
* @param w the new width
|
||||
* @param h the new height
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_size(lv_obj_t * obj, int32_t w, int32_t h);
|
||||
|
||||
/**
|
||||
* Recalculate the size of the object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the size has been changed
|
||||
*/
|
||||
bool lv_obj_refr_size(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @param w the new width
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_width(lv_obj_t * obj, int32_t w);
|
||||
|
||||
/**
|
||||
* Set the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @param h the new height
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_height(lv_obj_t * obj, int32_t h);
|
||||
|
||||
/**
|
||||
* Set the width reduced by the left and right padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @param w the width without paddings in pixels
|
||||
*/
|
||||
void lv_obj_set_content_width(lv_obj_t * obj, int32_t w);
|
||||
|
||||
/**
|
||||
* Set the height reduced by the top and bottom padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @param h the height without paddings in pixels
|
||||
*/
|
||||
void lv_obj_set_content_height(lv_obj_t * obj, int32_t h);
|
||||
|
||||
/**
|
||||
* Set a layout for an object
|
||||
* @param obj pointer to an object
|
||||
* @param layout pointer to a layout descriptor to set
|
||||
*/
|
||||
void lv_obj_set_layout(lv_obj_t * obj, uint32_t layout);
|
||||
|
||||
/**
|
||||
* Test whether the and object is positioned by a layout or not
|
||||
* @param obj pointer to an object to test
|
||||
* @return true: positioned by a layout; false: not positioned by a layout
|
||||
*/
|
||||
bool lv_obj_is_layout_positioned(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Mark the object for layout update.
|
||||
* @param obj pointer to an object whose children need to be updated
|
||||
*/
|
||||
void lv_obj_mark_layout_as_dirty(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Update the layout of an object.
|
||||
* @param obj pointer to an object whose position and size needs to be updated
|
||||
*/
|
||||
void lv_obj_update_layout(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Change the alignment of an object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
|
||||
*/
|
||||
void lv_obj_set_align(lv_obj_t * obj, lv_align_t align);
|
||||
|
||||
/**
|
||||
* Change the alignment of an object and set new coordinates.
|
||||
* Equivalent to:
|
||||
* lv_obj_set_align(obj, align);
|
||||
* lv_obj_set_pos(obj, x_ofs, y_ofs);
|
||||
* @param obj pointer to an object to align
|
||||
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
|
||||
* @param x_ofs x coordinate offset after alignment
|
||||
* @param y_ofs y coordinate offset after alignment
|
||||
*/
|
||||
void lv_obj_align(lv_obj_t * obj, lv_align_t align, int32_t x_ofs, int32_t y_ofs);
|
||||
|
||||
/**
|
||||
* Align an object to another object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param base pointer to another object (if NULL `obj`s parent is used). 'obj' will be aligned to it.
|
||||
* @param align type of alignment (see 'lv_align_t' enum)
|
||||
* @param x_ofs x coordinate offset after alignment
|
||||
* @param y_ofs y coordinate offset after alignment
|
||||
* @note if the position or size of `base` changes `obj` needs to be aligned manually again
|
||||
*/
|
||||
void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, int32_t x_ofs,
|
||||
int32_t y_ofs);
|
||||
|
||||
/**
|
||||
* Align an object to the center on its parent.
|
||||
* @param obj pointer to an object to align
|
||||
* @note if the parent size changes `obj` needs to be aligned manually again
|
||||
*/
|
||||
void lv_obj_center(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the transform matrix of an object
|
||||
* @param obj pointer to an object
|
||||
* @param matrix pointer to a matrix to set
|
||||
* @note `LV_DRAW_TRANSFORM_USE_MATRIX` needs to be enabled.
|
||||
*/
|
||||
void lv_obj_set_transform(lv_obj_t * obj, const lv_matrix_t * matrix);
|
||||
|
||||
/**
|
||||
* Reset the transform matrix of an object to identity matrix
|
||||
* @param obj pointer to an object
|
||||
* @note `LV_DRAW_TRANSFORM_USE_MATRIX` needs to be enabled.
|
||||
*/
|
||||
void lv_obj_reset_transform(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Copy the coordinates of an object to an area
|
||||
* @param obj pointer to an object
|
||||
* @param coords pointer to an area to store the coordinates
|
||||
*/
|
||||
void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * coords);
|
||||
|
||||
/**
|
||||
* Get the x coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the left side of its parent plus the parent's left padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the left padding of the parent, and not on the left edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
int32_t lv_obj_get_x(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the x2 coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the right side of its parent plus the parent's right padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the right padding of the parent, and not on the right edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
int32_t lv_obj_get_x2(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the y coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the top side of its parent plus the parent's top padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the top padding of the parent, and not on the top edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
int32_t lv_obj_get_y(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the y2 coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the bottom side of its parent plus the parent's bottom padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the bottom padding of the parent, and not on the bottom edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
int32_t lv_obj_get_y2(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the actually set x coordinate of object, i.e. the offset from the set alignment
|
||||
* @param obj pointer to an object
|
||||
* @return the set x coordinate
|
||||
*/
|
||||
int32_t lv_obj_get_x_aligned(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the actually set y coordinate of object, i.e. the offset from the set alignment
|
||||
* @param obj pointer to an object
|
||||
* @return the set y coordinate
|
||||
*/
|
||||
int32_t lv_obj_get_y_aligned(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the width in pixels
|
||||
*/
|
||||
int32_t lv_obj_get_width(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the height in pixels
|
||||
*/
|
||||
int32_t lv_obj_get_height(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the width reduced by the left and right padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the width which still fits into its parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
int32_t lv_obj_get_content_width(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height reduced by the top and bottom padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the height which still fits into the parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
int32_t lv_obj_get_content_height(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the area reduced by the paddings and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @param area the area which still fits into the parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
void lv_obj_get_content_coords(const lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Get the width occupied by the "parts" of the widget. E.g. the width of all columns of a table.
|
||||
* @param obj pointer to an object
|
||||
* @return the width of the virtually drawn content
|
||||
* @note This size independent from the real size of the widget.
|
||||
* It just tells how large the internal ("virtual") content is.
|
||||
*/
|
||||
int32_t lv_obj_get_self_width(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height occupied by the "parts" of the widget. E.g. the height of all rows of a table.
|
||||
* @param obj pointer to an object
|
||||
* @return the width of the virtually drawn content
|
||||
* @note This size independent from the real size of the widget.
|
||||
* It just tells how large the internal ("virtual") content is.
|
||||
*/
|
||||
int32_t lv_obj_get_self_height(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the style width actually used by the object after clamping the width within the min max range.
|
||||
* @param obj pointer to an object
|
||||
* @return the min/max/normal width set by `lv_obj_set_style_<min/max>_width()`
|
||||
* @note This is not the calculated size, so if the size was set as `LV_SIZE_CONTENT` or `LV_PCT()`
|
||||
* then that value will be returned.
|
||||
*/
|
||||
int32_t lv_obj_get_style_clamped_width(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the style height actually used by the object after clamping the height within the min max range.
|
||||
* @param obj pointer to an object
|
||||
* @return the min/max/normal height set by `lv_obj_set_style_<min/max>_height()`
|
||||
* @note This is not the calculated size, so if the size was set as `LV_SIZE_CONTENT` or `LV_PCT()`
|
||||
* then that value will be returned.
|
||||
*/
|
||||
int32_t lv_obj_get_style_clamped_height(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Determine if the object's resolved width was limited by its minimum width constraint.
|
||||
*
|
||||
* This function reports whether, in the most recent layout / size calculation, the object's
|
||||
* final (used) width had to be raised to satisfy a minimum width requirement.
|
||||
*
|
||||
* @param obj Pointer to a valid object.
|
||||
* @return true The computed width == the effective minimum width (i.e. it was clamped).
|
||||
* @return false The width is larger than the minimum (not min‑clamped).
|
||||
*/
|
||||
bool lv_obj_is_width_min(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Determine if the object's resolved height was limited by its minimum height constraint.
|
||||
*
|
||||
* This function reports whether, in the most recent layout / size calculation, the object's
|
||||
* final (used) height had to be raised to satisfy a minimum height requirement.
|
||||
*
|
||||
* @param obj Pointer to a valid object.
|
||||
* @return true The computed height == the effective minimum height (i.e. it was clamped).
|
||||
* @return false The height is larger than the minimum (not min‑clamped).
|
||||
*/
|
||||
bool lv_obj_is_height_min(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Determine if the object's resolved width was limited by its maximum width constraint.
|
||||
*
|
||||
* This function reports whether, in the most recent layout / size calculation, the object's
|
||||
* final (used) width had to be raised to satisfy a maximum width requirement.
|
||||
*
|
||||
* @param obj Pointer to a valid object.
|
||||
* @return true The computed width == the effective maximum width (i.e. it was clamped).
|
||||
* @return false The width is smaller than the maximum (not min‑clamped).
|
||||
*/
|
||||
bool lv_obj_is_width_max(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Determine if the object's resolved height was limited by its maximum height constraint.
|
||||
*
|
||||
* This function reports whether, in the most recent layout / size calculation, the object's
|
||||
* final (used) height had to be raised to satisfy a maximum height requirement.
|
||||
*
|
||||
* @param obj Pointer to a valid object.
|
||||
* @return true The computed height == the effective maximum height (i.e. it was clamped).
|
||||
* @return false The height is smaller than the maximum (not min‑clamped).
|
||||
*/
|
||||
bool lv_obj_is_height_max(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Handle if the size of the internal ("virtual") content of an object has changed.
|
||||
* @param obj pointer to an object
|
||||
* @return false: nothing happened; true: refresh happened
|
||||
*/
|
||||
bool lv_obj_refresh_self_size(lv_obj_t * obj);
|
||||
|
||||
void lv_obj_refr_pos(lv_obj_t * obj);
|
||||
|
||||
void lv_obj_move_to(lv_obj_t * obj, int32_t x, int32_t y);
|
||||
|
||||
void lv_obj_move_children_by(lv_obj_t * obj, int32_t x_diff, int32_t y_diff, bool ignore_floating);
|
||||
|
||||
/**
|
||||
* Get the transform matrix of an object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the transform matrix or NULL if not set
|
||||
*/
|
||||
const lv_matrix_t * lv_obj_get_transform(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* 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 flags OR-ed valued of :cpp:enum:`lv_obj_point_transform_flag_t`
|
||||
*/
|
||||
void lv_obj_transform_point(const lv_obj_t * obj, lv_point_t * p, lv_obj_point_transform_flag_t flags);
|
||||
|
||||
/**
|
||||
* Transform an array of points using the angle and zoom style properties of an object
|
||||
* @param obj pointer to an object whose style properties should be used
|
||||
* @param points the array of points to transform, the result will be written back here too
|
||||
* @param count number of points in the array
|
||||
* @param flags OR-ed valued of :cpp:enum:`lv_obj_point_transform_flag_t`
|
||||
*/
|
||||
void lv_obj_transform_point_array(const lv_obj_t * obj, lv_point_t points[], size_t count,
|
||||
lv_obj_point_transform_flag_t flags);
|
||||
|
||||
/**
|
||||
* 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 flags OR-ed valued of :cpp:enum:`lv_obj_point_transform_flag_t`
|
||||
*/
|
||||
void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, lv_obj_point_transform_flag_t flags);
|
||||
|
||||
/**
|
||||
* Mark an area of an object as invalid.
|
||||
* The area will be truncated to the object's area and marked for redraw.
|
||||
* @param obj pointer to an object
|
||||
* @param area the area to redraw
|
||||
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
|
||||
* (maybe it was off-screen or fully clipped)
|
||||
*/
|
||||
lv_result_t lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Mark the object as invalid to redrawn its area
|
||||
* @param obj pointer to an object
|
||||
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
|
||||
* (maybe it was off-screen or fully clipped)
|
||||
*/
|
||||
lv_result_t lv_obj_invalidate(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Tell whether an area of an object is visible (even partially) now or not
|
||||
* @param obj pointer to an object
|
||||
* @param area the are to check. The visible part of the area will be written back here.
|
||||
* @return true visible; false not visible (hidden, out of parent, on other screen, etc)
|
||||
*/
|
||||
bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Tell whether an object is visible (even partially) now or not
|
||||
* @param obj pointer to an object
|
||||
* @return true: visible; false not visible (hidden, out of parent, on other screen, etc)
|
||||
*/
|
||||
bool lv_obj_is_visible(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the size of an extended clickable area
|
||||
* @param obj pointer to an object
|
||||
* @param size extended clickable area in all 4 directions [px]
|
||||
*/
|
||||
void lv_obj_set_ext_click_area(lv_obj_t * obj, int32_t size);
|
||||
|
||||
/**
|
||||
* Get the an area where to object can be clicked.
|
||||
* It's the object's normal area plus the extended click area.
|
||||
* @param obj pointer to an object
|
||||
* @param area store the result area here
|
||||
*/
|
||||
void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Hit-test an object given a particular point in screen space.
|
||||
* @param obj object to hit-test
|
||||
* @param point screen-space point (absolute coordinate)
|
||||
* @return true: if the object is considered under the point
|
||||
*/
|
||||
bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Clamp a width between min and max width. If the min/max width is in percentage value use the ref_width
|
||||
* @param width width to clamp
|
||||
* @param min_width the minimal width
|
||||
* @param max_width the maximal width
|
||||
* @param ref_width the reference width used when min/max width is in percentage
|
||||
* @return the clamped width
|
||||
*/
|
||||
int32_t lv_clamp_width(int32_t width, int32_t min_width, int32_t max_width, int32_t ref_width);
|
||||
|
||||
/**
|
||||
* Clamp a height between min and max height. If the min/max height is in percentage value use the ref_height
|
||||
* @param height height to clamp
|
||||
* @param min_height the minimal height
|
||||
* @param max_height the maximal height
|
||||
* @param ref_height the reference height used when min/max height is in percentage
|
||||
* @return the clamped height
|
||||
*/
|
||||
int32_t lv_clamp_height(int32_t height, int32_t min_height, int32_t max_height, int32_t ref_height);
|
||||
|
||||
/**
|
||||
* @brief Calculates the width in pixels of an LVGL object based on its style and parent for a given width `prop`.
|
||||
* @param obj Pointer to the LVGL object whose width is being calculated.
|
||||
* @param prop Which style width to calculate for. Valid values are: LV_STYLE_WIDTH, LV_STYLE_MIN_WIDTH, or
|
||||
* LV_STYLE_MAX_WIDTH.
|
||||
* @return The computed width for the object:
|
||||
* @note If the style width is a fixed value, that value is returned.
|
||||
* @note If the style width is `LV_SIZE_CONTENT`, the content width is calculated and returned.
|
||||
* @note If the style width is a `LV_PCT()`, the percentage is applied to the parent's width.
|
||||
*/
|
||||
int32_t lv_obj_calc_dynamic_width(lv_obj_t * obj, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* @brief Calculates the height in pixels of an LVGL object based on its style and parent for a given height `prop`.
|
||||
* @param obj Pointer to the LVGL object whose height is being calculated.
|
||||
* @param prop Which style height to calculate for. Valid values are: LV_STYLE_HEIGHT, LV_STYLE_MIN_HEIGHT, or
|
||||
* LV_STYLE_MAX_HEIGHT.
|
||||
* @return The computed height for the object:
|
||||
* @note If the style height is a fixed value, that value is returned.
|
||||
* @note If the style height is `LV_SIZE_CONTENT`, the content height is calculated and returned.
|
||||
* @note If the style height is a `LV_PCT()`, the percentage is applied to the parent's height.
|
||||
*/
|
||||
int32_t lv_obj_calc_dynamic_height(lv_obj_t * obj, lv_style_prop_t prop);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_POS_H*/
|
||||
103
inc/lvgl/src/core/lv_obj_private.h
Normal file
103
inc/lvgl/src/core/lv_obj_private.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file lv_obj_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_PRIVATE_H
|
||||
#define LV_OBJ_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_ext_data.h"
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Special, rarely used attributes.
|
||||
* They are allocated automatically if any elements is set.
|
||||
*/
|
||||
struct _lv_obj_spec_attr_t {
|
||||
lv_obj_t ** children; /**< Store the pointer of the children in an array.*/
|
||||
lv_group_t * group_p;
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_t * matrix; /**< The transform matrix*/
|
||||
#endif
|
||||
lv_event_list_t event_list;
|
||||
#if LV_USE_OBJ_NAME
|
||||
const char * name; /**< Pointer to the name */
|
||||
#endif
|
||||
lv_point_t scroll; /**< The current X/Y scroll offset*/
|
||||
|
||||
int32_t ext_click_pad; /**< Extra click padding in all direction*/
|
||||
int32_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/
|
||||
|
||||
uint16_t child_cnt; /**< Number of children*/
|
||||
uint16_t scrollbar_mode : 2; /**< How to display scrollbars, see `lv_scrollbar_mode_t`*/
|
||||
uint16_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally, see `lv_scroll_snap_t`*/
|
||||
uint16_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/
|
||||
uint16_t scroll_dir : 4; /**< The allowed scroll direction(s), see `lv_dir_t`*/
|
||||
uint16_t layer_type : 2; /**< Cache the layer type here. Element of lv_intermediate_layer_type_t */
|
||||
uint16_t name_static : 1; /**< 1: `name` was not dynamically allocated */
|
||||
};
|
||||
|
||||
struct _lv_obj_t {
|
||||
#if LV_USE_EXT_DATA
|
||||
lv_ext_data_t ext_data;
|
||||
#endif
|
||||
const lv_obj_class_t * class_p;
|
||||
lv_obj_t * parent;
|
||||
lv_obj_spec_attr_t * spec_attr;
|
||||
lv_obj_style_t * styles;
|
||||
#if LV_OBJ_STYLE_CACHE
|
||||
uint32_t style_main_prop_is_set;
|
||||
uint32_t style_other_prop_is_set;
|
||||
#endif
|
||||
void * user_data;
|
||||
#if LV_USE_OBJ_ID
|
||||
void * id;
|
||||
#endif
|
||||
lv_area_t coords;
|
||||
lv_obj_flag_t flags;
|
||||
uint16_t state;
|
||||
uint16_t layout_inv : 1;
|
||||
uint16_t readjust_scroll_after_layout : 1;
|
||||
uint16_t scr_layout_inv : 1;
|
||||
uint16_t skip_trans : 1;
|
||||
uint16_t style_cnt : 6;
|
||||
uint16_t h_layout : 1;
|
||||
uint16_t w_layout : 1;
|
||||
uint16_t h_ignore_size : 1; /* ignore this obj when calculating content height of parent */
|
||||
uint16_t w_ignore_size : 1; /* ignore this obj when calculating content width of parent */
|
||||
uint16_t is_deleting : 1;
|
||||
uint16_t radio_button : 1; /**< Allow only one RADIO_BUTTON sibling to be checked*/
|
||||
|
||||
/** The widget is rendered at least once already.
|
||||
* It's used to skip initial animations and transitions. */
|
||||
uint16_t rendered : 1;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_PRIVATE_H*/
|
||||
339
inc/lvgl/src/core/lv_obj_property.c
Normal file
339
inc/lvgl/src/core/lv_obj_property.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/**
|
||||
* @file lv_obj_property.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_private.h"
|
||||
#include "../core/lv_obj.h"
|
||||
#include "../stdlib/lv_string.h"
|
||||
#include "../misc/lv_utils.h"
|
||||
#include "lv_obj_property.h"
|
||||
#include "lv_obj_class_private.h"
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define HANDLE_PROPERTY_TYPE(type, field) \
|
||||
if(!set) { \
|
||||
value->field = ((lv_property_get_##type##_t)(prop->getter))(obj); \
|
||||
} else { \
|
||||
switch(LV_PROPERTY_ID_TYPE2(prop->id)) { \
|
||||
case LV_PROPERTY_ID_INVALID: \
|
||||
((lv_property_set_##type##_t)(prop->setter))(obj, value->field); \
|
||||
break; \
|
||||
case LV_PROPERTY_TYPE_INT: \
|
||||
((lv_property_set_##type##_integer_t)(prop->setter))(obj, value->arg1.field, value->arg2.num); \
|
||||
break; \
|
||||
case LV_PROPERTY_TYPE_BOOL: \
|
||||
((lv_property_set_##type##_boolean_t)(prop->setter))(obj, value->arg1.field, value->arg2.enable); \
|
||||
break; \
|
||||
case LV_PROPERTY_TYPE_PRECISE: \
|
||||
((lv_property_set_##type##_precise_t)(prop->setter))(obj, value->arg1.field, value->arg2.precise); \
|
||||
break; \
|
||||
case LV_PROPERTY_TYPE_COLOR: \
|
||||
((lv_property_set_##type##_color_t)(prop->setter))(obj, value->arg1.field, value->arg2.color); \
|
||||
break; \
|
||||
case LV_PROPERTY_TYPE_POINTER: \
|
||||
case LV_PROPERTY_TYPE_IMGSRC: \
|
||||
case LV_PROPERTY_TYPE_TEXT: \
|
||||
case LV_PROPERTY_TYPE_OBJ: \
|
||||
case LV_PROPERTY_TYPE_DISPLAY: \
|
||||
case LV_PROPERTY_TYPE_FONT: \
|
||||
((lv_property_set_##type##_pointer_t)(prop->setter))(obj, value->arg1.field, value->arg2.ptr); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef int32_t integer;
|
||||
typedef bool boolean;
|
||||
typedef lv_value_precise_t precise;
|
||||
typedef lv_color_t color;
|
||||
typedef const void * pointer;
|
||||
|
||||
#define DEFINE_PROPERTY_SETTER_TYPES(type) \
|
||||
typedef void (*lv_property_set_##type##_t)(lv_obj_t *, type); \
|
||||
typedef void (*lv_property_set_##type##_integer_t)(lv_obj_t *, type, int32_t); \
|
||||
typedef void (*lv_property_set_##type##_boolean_t)(lv_obj_t *, type, bool); \
|
||||
typedef void (*lv_property_set_##type##_precise_t)(lv_obj_t *, type, lv_value_precise_t); \
|
||||
typedef void (*lv_property_set_##type##_color_t)(lv_obj_t *, type, lv_color_t); \
|
||||
typedef void (*lv_property_set_##type##_pointer_t)(lv_obj_t *, type, const void *)
|
||||
|
||||
DEFINE_PROPERTY_SETTER_TYPES(integer);
|
||||
DEFINE_PROPERTY_SETTER_TYPES(boolean);
|
||||
DEFINE_PROPERTY_SETTER_TYPES(precise);
|
||||
DEFINE_PROPERTY_SETTER_TYPES(color);
|
||||
DEFINE_PROPERTY_SETTER_TYPES(pointer);
|
||||
|
||||
typedef void (*lv_property_set_point_t)(lv_obj_t *, lv_point_t *);
|
||||
typedef lv_result_t (*lv_property_setter_t)(lv_obj_t *, lv_prop_id_t, const lv_property_t *);
|
||||
|
||||
typedef integer(*lv_property_get_integer_t)(const lv_obj_t *);
|
||||
typedef bool (*lv_property_get_boolean_t)(const lv_obj_t *);
|
||||
typedef lv_value_precise_t (*lv_property_get_precise_t)(const lv_obj_t *);
|
||||
typedef lv_color_t (*lv_property_get_color_t)(const lv_obj_t *);
|
||||
typedef void * (*lv_property_get_pointer_t)(const lv_obj_t *);
|
||||
typedef lv_point_t (*lv_property_get_point_t)(lv_obj_t *);
|
||||
|
||||
typedef lv_result_t (*lv_property_getter_t)(const lv_obj_t *, lv_prop_id_t, lv_property_t *);
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set);
|
||||
static int property_name_compare(const void * ref, const void * element);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value)
|
||||
{
|
||||
LV_ASSERT(obj && value);
|
||||
|
||||
uint32_t index = LV_PROPERTY_ID_INDEX(value->id);
|
||||
if(value->id == LV_PROPERTY_ID_INVALID || index > LV_PROPERTY_ID_ANY) {
|
||||
LV_LOG_WARN("Invalid property id set to %p", obj);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
if(index < LV_PROPERTY_ID_START) {
|
||||
lv_obj_set_local_style_prop(obj, index, value->style, value->selector);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
return obj_property(obj, value->id, (lv_property_t *)value, true);
|
||||
}
|
||||
|
||||
lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count)
|
||||
{
|
||||
for(uint32_t i = 0; i < count; i++) {
|
||||
lv_result_t result = lv_obj_set_property(obj, &value[i]);
|
||||
if(result != LV_RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id)
|
||||
{
|
||||
lv_result_t result;
|
||||
lv_property_t value = { 0 };
|
||||
|
||||
uint32_t index = LV_PROPERTY_ID_INDEX(id);
|
||||
if(id == LV_PROPERTY_ID_INVALID || index > LV_PROPERTY_ID_ANY) {
|
||||
LV_LOG_WARN("Invalid property id to get from %p", obj);
|
||||
value.id = LV_PROPERTY_ID_INVALID;
|
||||
value.num = 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
if(index < LV_PROPERTY_ID_START) {
|
||||
value.style = lv_obj_get_style_prop(obj, LV_PART_MAIN, index);
|
||||
value.id = id;
|
||||
value.selector = LV_PART_MAIN | obj->state;
|
||||
return value;
|
||||
}
|
||||
|
||||
result = obj_property(obj, id, &value, false);
|
||||
if(result != LV_RESULT_OK)
|
||||
value.id = LV_PROPERTY_ID_INVALID;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, lv_part_t part)
|
||||
{
|
||||
lv_property_t value;
|
||||
uint32_t index = LV_PROPERTY_ID_INDEX(id);
|
||||
|
||||
if(index == LV_PROPERTY_ID_INVALID || index >= LV_PROPERTY_ID_START) {
|
||||
LV_LOG_WARN("invalid style property id 0x%" LV_PRIx32, id);
|
||||
value.id = LV_PROPERTY_ID_INVALID;
|
||||
value.num = 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
value.style = lv_obj_get_style_prop(obj, part, index);
|
||||
value.id = id;
|
||||
value.selector = part | obj->state;
|
||||
return value;
|
||||
}
|
||||
|
||||
lv_prop_id_t lv_style_property_get_id(const char * name)
|
||||
{
|
||||
#if LV_USE_OBJ_PROPERTY_NAME
|
||||
lv_property_name_t * found;
|
||||
/*Check style property*/
|
||||
found = lv_utils_bsearch(name, lv_style_property_names, sizeof(lv_style_property_names) / sizeof(lv_property_name_t),
|
||||
sizeof(lv_property_name_t), property_name_compare);
|
||||
if(found) return found->id;
|
||||
#else
|
||||
LV_UNUSED(name);
|
||||
#endif
|
||||
return LV_PROPERTY_ID_INVALID;
|
||||
}
|
||||
|
||||
lv_prop_id_t lv_obj_class_property_get_id(const lv_obj_class_t * clz, const char * name)
|
||||
{
|
||||
#if LV_USE_OBJ_PROPERTY_NAME
|
||||
const lv_property_name_t * names;
|
||||
lv_property_name_t * found;
|
||||
|
||||
names = clz->property_names;
|
||||
if(names == NULL) {
|
||||
/* try base class*/
|
||||
return LV_PROPERTY_ID_INVALID;
|
||||
}
|
||||
|
||||
found = lv_utils_bsearch(name, names, clz->names_count, sizeof(lv_property_name_t), property_name_compare);
|
||||
if(found) return found->id;
|
||||
#else
|
||||
LV_UNUSED(obj);
|
||||
LV_UNUSED(name);
|
||||
LV_UNUSED(property_name_compare);
|
||||
#endif
|
||||
return LV_PROPERTY_ID_INVALID;
|
||||
}
|
||||
|
||||
lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name)
|
||||
{
|
||||
#if LV_USE_OBJ_PROPERTY_NAME
|
||||
const lv_obj_class_t * clz;
|
||||
lv_prop_id_t id;
|
||||
|
||||
for(clz = obj->class_p; clz; clz = clz->base_class) {
|
||||
id = lv_obj_class_property_get_id(clz, name);
|
||||
if(id != LV_PROPERTY_ID_INVALID) return id;
|
||||
}
|
||||
|
||||
/*Check style property*/
|
||||
id = lv_style_property_get_id(name);
|
||||
if(id != LV_PROPERTY_ID_INVALID) return id;
|
||||
#else
|
||||
LV_UNUSED(obj);
|
||||
LV_UNUSED(name);
|
||||
LV_UNUSED(property_name_compare);
|
||||
#endif
|
||||
return LV_PROPERTY_ID_INVALID;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set)
|
||||
{
|
||||
const lv_property_ops_t * properties;
|
||||
const lv_property_ops_t * prop;
|
||||
|
||||
const lv_obj_class_t * clz;
|
||||
uint32_t index = LV_PROPERTY_ID_INDEX(id);
|
||||
|
||||
for(clz = obj->class_p ; clz; clz = clz->base_class) {
|
||||
properties = clz->properties;
|
||||
if(properties == NULL) {
|
||||
/* try base class*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if(id != LV_PROPERTY_ID_ANY && (index < clz->prop_index_start || index > clz->prop_index_end)) {
|
||||
/* try base class*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check if there's setter available for this class*/
|
||||
for(uint32_t i = 0; i < clz->properties_count; i++) {
|
||||
prop = &properties[i];
|
||||
|
||||
/*pass id and value directly to widget's property method*/
|
||||
if(prop->id == LV_PROPERTY_ID_ANY) {
|
||||
value->id = prop->id;
|
||||
if(set) return ((lv_property_setter_t)prop->setter)(obj, id, value);
|
||||
else return ((lv_property_getter_t)prop->getter)(obj, id, value);
|
||||
}
|
||||
|
||||
/*Not this id, check next*/
|
||||
if(prop->id != id)
|
||||
continue;
|
||||
|
||||
/*id matched but we got null pointer to functions*/
|
||||
if(set ? prop->setter == NULL : prop->getter == NULL) {
|
||||
LV_LOG_WARN("NULL %s provided, id: 0x%" LV_PRIx32, set ? "setter" : "getter", id);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
/*Update value id if it's a read*/
|
||||
if(!set) value->id = prop->id;
|
||||
|
||||
switch(LV_PROPERTY_ID_TYPE(prop->id)) {
|
||||
case LV_PROPERTY_TYPE_INT:
|
||||
HANDLE_PROPERTY_TYPE(integer, num);
|
||||
break;
|
||||
case LV_PROPERTY_TYPE_BOOL:
|
||||
HANDLE_PROPERTY_TYPE(boolean, enable);
|
||||
break;
|
||||
case LV_PROPERTY_TYPE_PRECISE:
|
||||
HANDLE_PROPERTY_TYPE(precise, precise);
|
||||
break;
|
||||
case LV_PROPERTY_TYPE_COLOR:
|
||||
HANDLE_PROPERTY_TYPE(color, color);
|
||||
break;
|
||||
case LV_PROPERTY_TYPE_POINTER:
|
||||
case LV_PROPERTY_TYPE_IMGSRC:
|
||||
case LV_PROPERTY_TYPE_TEXT:
|
||||
case LV_PROPERTY_TYPE_OBJ:
|
||||
case LV_PROPERTY_TYPE_DISPLAY:
|
||||
case LV_PROPERTY_TYPE_FONT:
|
||||
HANDLE_PROPERTY_TYPE(pointer, ptr);
|
||||
break;
|
||||
case LV_PROPERTY_TYPE_POINT: {
|
||||
lv_point_t * point = &value->point;
|
||||
if(set)((lv_property_set_point_t)(prop->setter))(obj, point);
|
||||
else *point = ((lv_property_get_point_t)(prop->getter))(obj);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LV_LOG_WARN("Unknown property id: 0x%08" LV_PRIx32, prop->id);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/*If no setter found, try base class then*/
|
||||
}
|
||||
|
||||
LV_LOG_WARN("Unknown property id: 0x%08" LV_PRIx32, id);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
static int property_name_compare(const void * ref, const void * element)
|
||||
{
|
||||
const lv_property_name_t * prop = element;
|
||||
return lv_strcmp(ref, prop->name);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OBJ_PROPERTY*/
|
||||
283
inc/lvgl/src/core/lv_obj_property.h
Normal file
283
inc/lvgl/src/core/lv_obj_property.h
Normal file
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* @file lv_obj_property.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_PROPERTY_H
|
||||
#define LV_OBJ_PROPERTY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "lv_obj_style.h"
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/*All possible property value types*/
|
||||
#define LV_PROPERTY_TYPE_INVALID 0 /*Use default 0 as invalid to detect program outliers*/
|
||||
#define LV_PROPERTY_TYPE_INT 1 /*int32_t type*/
|
||||
#define LV_PROPERTY_TYPE_PRECISE 2 /*lv_value_precise_t, int32_t or float depending on LV_USE_FLOAT*/
|
||||
#define LV_PROPERTY_TYPE_COLOR 3 /*ARGB8888 type*/
|
||||
#define LV_PROPERTY_TYPE_POINT 4 /*lv_point_t */
|
||||
#define LV_PROPERTY_TYPE_POINTER 5 /*void * pointer*/
|
||||
#define LV_PROPERTY_TYPE_IMGSRC 6 /*Special pointer for image*/
|
||||
#define LV_PROPERTY_TYPE_TEXT 7 /*Special pointer of char* */
|
||||
#define LV_PROPERTY_TYPE_OBJ 8 /*Special pointer of lv_obj_t* */
|
||||
#define LV_PROPERTY_TYPE_DISPLAY 9 /*Special pointer of lv_display_t* */
|
||||
#define LV_PROPERTY_TYPE_FONT 10 /*Special pointer of lv_font_t* */
|
||||
#define LV_PROPERTY_TYPE_BOOL 11 /*int32_t type*/
|
||||
|
||||
#define LV_PROPERTY_TYPE_SHIFT 28
|
||||
#define LV_PROPERTY_TYPE2_SHIFT 24
|
||||
|
||||
/* Example:
|
||||
* LV_PROPERTY_ID(OBJ, FLAG_CLICKABLE, LV_PROPERTY_TYPE_INT, 1),
|
||||
* produces
|
||||
* LV_PROPERTY_OBJ_FLAG_CLICKABLE = (LV_PROPERTY_OBJ_START + (1)) | ((LV_PROPERTY_TYPE_INT) << LV_PROPERTY_TYPE_SHIFT)
|
||||
*/
|
||||
#define LV_PROPERTY_ID(clz, name, type, index) LV_PROPERTY_## clz ##_##name = (LV_PROPERTY_## clz ##_START + ((int)index)) | ((type) << LV_PROPERTY_TYPE_SHIFT)
|
||||
|
||||
/* Example:
|
||||
* LV_PROPERTY_ID2(SLIDER, VALUE, LV_PROPERTY_TYPE_INT, LV_PROPERTY_TYPE_BOOL, 0)
|
||||
* produces
|
||||
* LV_PROPERTY_SLIDER_VALUE = (LV_PROPERTY_SLIDER_START + (0)) | ((LV_PROPERTY_TYPE_INT) << LV_PROPERTY_TYPE_SHIFT) | ((LV_PROPERTY_TYPE_BOOL) << LV_PROPERTY_TYPE2_SHIFT)
|
||||
*/
|
||||
#define LV_PROPERTY_ID2(clz, name, type, type2, index) LV_PROPERTY_ID(clz, name, type, index) | ((type2) << LV_PROPERTY_TYPE2_SHIFT)
|
||||
|
||||
#define LV_PROPERTY_ID_TYPE(id) ((id) >> LV_PROPERTY_TYPE_SHIFT)
|
||||
#define LV_PROPERTY_ID_TYPE2(id) ((id) >> LV_PROPERTY_TYPE_SHIFT)
|
||||
#define LV_PROPERTY_ID_INDEX(id) ((id) & 0xfffffff)
|
||||
|
||||
/*Set properties from an array of lv_property_t*/
|
||||
#define LV_OBJ_SET_PROPERTY_ARRAY(obj, array) lv_obj_set_properties(obj, array, LV_ARRAYLEN(array))
|
||||
|
||||
/* Helper to implement class definition of property and property names */
|
||||
/* *INDENT-OFF* */
|
||||
#if LV_USE_OBJ_PROPERTY_NAME
|
||||
#define LV_PROPERTY_CLASS_FIELDS(widget, uppercase) \
|
||||
.prop_index_start = LV_PROPERTY_##uppercase##_START, \
|
||||
.prop_index_end = LV_PROPERTY_##uppercase##_END, \
|
||||
.properties = lv_##widget##_properties, \
|
||||
.properties_count = LV_ARRAYLEN(lv_##widget##_properties), \
|
||||
.property_names = lv_##widget##_property_names, \
|
||||
.names_count = LV_ARRAYLEN(lv_##widget##_property_names)
|
||||
#else
|
||||
#define LV_PROPERTY_CLASS_FIELDS(widget, uppercase) \
|
||||
.prop_index_start = LV_PROPERTY_##uppercase##_START, \
|
||||
.prop_index_end = LV_PROPERTY_##uppercase##_END, \
|
||||
.properties = lv_##widget##_properties, \
|
||||
.properties_count = LV_ARRAYLEN(lv_##widget##_properties)
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Group of predefined widget ID start value.
|
||||
*/
|
||||
enum _lv_prop_id_range_boundary_t {
|
||||
LV_PROPERTY_ID_INVALID = 0,
|
||||
|
||||
/*ID 0x01 to 0xff are style ID, check lv_style_prop_t*/
|
||||
LV_PROPERTY_STYLE_START = 0x00,
|
||||
|
||||
LV_PROPERTY_ID_START = 0x0100, /*ID smaller than 0xff is style ID*/
|
||||
/*Define the property ID for every widget here. */
|
||||
LV_PROPERTY_OBJ_START = 0x0100, /* lv_obj.c */
|
||||
LV_PROPERTY_IMAGE_START = 0x0200, /* lv_image.c */
|
||||
LV_PROPERTY_LABEL_START = 0x0300, /* lv_label.c */
|
||||
LV_PROPERTY_KEYBOARD_START = 0x0400, /* lv_keyboard.c */
|
||||
LV_PROPERTY_TEXTAREA_START = 0x0500, /* lv_textarea.c */
|
||||
LV_PROPERTY_ROLLER_START = 0x0600, /* lv_roller.c */
|
||||
LV_PROPERTY_DROPDOWN_START = 0x0700, /* lv_dropdown.c */
|
||||
LV_PROPERTY_SLIDER_START = 0x0800, /* lv_slider.c */
|
||||
LV_PROPERTY_ANIMIMAGE_START = 0x0900, /* lv_animimage.c */
|
||||
LV_PROPERTY_ARC_START = 0x0a00, /* lv_arc.c */
|
||||
LV_PROPERTY_BAR_START = 0x0b00, /* lv_bar.c */
|
||||
LV_PROPERTY_SWITCH_START = 0x0c00, /* lv_switch.c */
|
||||
LV_PROPERTY_CHECKBOX_START = 0x0d00, /* lv_checkbox.c */
|
||||
LV_PROPERTY_LED_START = 0x0e00, /* lv_led.c */
|
||||
LV_PROPERTY_LINE_START = 0x0f00, /* lv_line.c */
|
||||
LV_PROPERTY_SCALE_START = 0x1000, /* lv_scale.c */
|
||||
LV_PROPERTY_SPINBOX_START = 0x1100, /* lv_spinbox.c */
|
||||
LV_PROPERTY_SPINNER_START = 0x1200, /* lv_spinner.c */
|
||||
LV_PROPERTY_TABLE_START = 0x1300, /* lv_table.c */
|
||||
LV_PROPERTY_TABVIEW_START = 0x1400, /* lv_tabview.c */
|
||||
LV_PROPERTY_BUTTONMATRIX_START = 0x1500, /* lv_buttonmatrix.c */
|
||||
LV_PROPERTY_SPAN_START = 0x1600, /* lv_span.c */
|
||||
LV_PROPERTY_MENU_START = 0x1700, /* lv_menu.c */
|
||||
LV_PROPERTY_CHART_START = 0x1800, /* lv_chart.c */
|
||||
|
||||
/*Special ID, use it to extend ID and make sure it's unique and compile time determinant*/
|
||||
LV_PROPERTY_ID_BUILTIN_LAST = 0xffff, /*ID of 0x10000 ~ 0xfffffff is reserved for user*/
|
||||
|
||||
LV_PROPERTY_ID_ANY = 0x7ffffffe, /*Special ID used by lvgl to intercept all setter/getter call.*/
|
||||
};
|
||||
|
||||
struct _lv_property_name_t {
|
||||
const char * name;
|
||||
lv_prop_id_t id;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
lv_prop_id_t id;
|
||||
union {
|
||||
int32_t num; /**< Signed integer number (enums or "normal" numbers)*/
|
||||
uint32_t num_u; /**< Unsigned integer number (opacity, Booleans) */
|
||||
bool enable; /**< Booleans */
|
||||
const void * ptr; /**< Constant pointers (font, cone text, etc.) */
|
||||
lv_color_t color; /**< Colors */
|
||||
lv_value_precise_t precise; /**< float or int for precise value */
|
||||
lv_point_t point; /**< Point, contains two int32_t */
|
||||
|
||||
struct {
|
||||
/**
|
||||
* Note that place struct member `style` at first place is intended.
|
||||
* `style` shares same memory with `num`, `ptr`, `color`.
|
||||
* So we set the style value directly without using `prop.style.num`.
|
||||
*
|
||||
* E.g.
|
||||
*
|
||||
* static const lv_property_t obj_pos_x = {
|
||||
* .id = LV_PROPERTY_STYLE_X,
|
||||
* .num = 123,
|
||||
* .selector = LV_STATE_PRESSED,
|
||||
* }
|
||||
*
|
||||
* instead of:
|
||||
* static const lv_property_t obj_pos_x = {
|
||||
* .id = LV_PROPERTY_STYLE_X,
|
||||
* .style.num = 123, // note this line.
|
||||
* .selector = LV_STATE_PRESSED,
|
||||
* }
|
||||
*/
|
||||
lv_style_value_t style; /**< Make sure it's the first element in struct. */
|
||||
uint32_t selector; /**< Style selector, lv_part_t | lv_state_t */
|
||||
};
|
||||
|
||||
/**
|
||||
* For some properties like slider range, it contains two simple (4-byte) values
|
||||
* so we can use `arg1.num` and `arg2.num` to set the argument.
|
||||
*/
|
||||
struct {
|
||||
union {
|
||||
int32_t num;
|
||||
uint32_t num_u;
|
||||
bool enable;
|
||||
const void * ptr;
|
||||
lv_color_t color;
|
||||
lv_value_precise_t precise;
|
||||
} arg1, arg2;
|
||||
};
|
||||
};
|
||||
} lv_property_t;
|
||||
|
||||
typedef struct {
|
||||
lv_prop_id_t id;
|
||||
|
||||
void * setter; /**< Callback used to set property. */
|
||||
void * getter; /**< Callback used to get property. */
|
||||
} lv_property_ops_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set Widget property.
|
||||
* @param obj pointer to Widget
|
||||
* @param value property value to set
|
||||
* @return return LV_RESULT_OK if call succeeded
|
||||
*/
|
||||
lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value);
|
||||
|
||||
/**
|
||||
* Set multiple Widget properties. Helper `LV_OBJ_SET_PROPERTY_ARRAY` can be used for constant property array.
|
||||
* @param obj pointer to Widget
|
||||
* @param value property value array to set
|
||||
* @param count number of array elements
|
||||
* @return return LV_RESULT_OK if call succeeded
|
||||
*/
|
||||
lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Read property value from Widget.
|
||||
* If id is a style property, computes the style of PART_MAIN.
|
||||
* @param obj pointer to Widget
|
||||
* @param id ID of property to read
|
||||
* @return return property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if read failed.
|
||||
*/
|
||||
lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id);
|
||||
|
||||
/**
|
||||
* Read style property value from Widget
|
||||
* @param obj pointer to Widget
|
||||
* @param id ID of style property
|
||||
* @param part part for which the style property should be computed
|
||||
* @return return property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if read failed.
|
||||
*/
|
||||
lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, lv_part_t part);
|
||||
|
||||
/**
|
||||
* Get property ID by recursively searching for name in Widget's class hierarchy, and
|
||||
* if still not found, then search style properties.
|
||||
* Requires to enabling `LV_USE_OBJ_PROPERTY_NAME`.
|
||||
* @param obj pointer to Widget whose class and base-class hierarchy are to be searched.
|
||||
* @param name property name
|
||||
* @return property ID found or `LV_PROPERTY_ID_INVALID` if not found.
|
||||
*/
|
||||
lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name);
|
||||
|
||||
/**
|
||||
* Get property ID by doing a non-recursive search for name directly in Widget class properties.
|
||||
* Requires enabling `LV_USE_OBJ_PROPERTY_NAME`.
|
||||
* @param clz pointer to Widget class that has specified property.
|
||||
* @param name property name
|
||||
* @return property ID found or `LV_PROPERTY_ID_INVALID` if not found.
|
||||
*/
|
||||
lv_prop_id_t lv_obj_class_property_get_id(const lv_obj_class_t * clz, const char * name);
|
||||
|
||||
/**
|
||||
* Get style property ID by name. Requires enabling `LV_USE_OBJ_PROPERTY_NAME`.
|
||||
* @param name property name
|
||||
* @return property ID found or `LV_PROPERTY_ID_INVALID` if not found.
|
||||
*/
|
||||
lv_prop_id_t lv_style_property_get_id(const char * name);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#include "../widgets/property/lv_obj_property_names.h"
|
||||
#include "../widgets/property/lv_style_properties.h"
|
||||
|
||||
#else
|
||||
#define LV_PROPERTY_CLASS_FIELDS(widget, uppercase)
|
||||
#endif /*LV_USE_OBJ_PROPERTY*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_PROPERTY_H*/
|
||||
817
inc/lvgl/src/core/lv_obj_scroll.c
Normal file
817
inc/lvgl/src/core/lv_obj_scroll.c
Normal file
@@ -0,0 +1,817 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_scroll_private.h"
|
||||
#include "../misc/lv_anim_private.h"
|
||||
#include "lv_obj_private.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "../indev/lv_indev_scroll.h"
|
||||
#include "../display/lv_display.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_obj_class)
|
||||
#ifndef SCROLL_ANIM_TIME_MIN
|
||||
#define SCROLL_ANIM_TIME_MIN 200 /*ms*/
|
||||
#endif
|
||||
#ifndef SCROLL_ANIM_TIME_MAX
|
||||
#define SCROLL_ANIM_TIME_MAX 400 /*ms*/
|
||||
#endif
|
||||
#define SCROLLBAR_MIN_SIZE (LV_DPX(10))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void scroll_x_anim(void * obj, int32_t v);
|
||||
static void scroll_y_anim(void * obj, int32_t v);
|
||||
static void scroll_end_cb(lv_anim_t * a);
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(obj->spec_attr->scrollbar_mode == mode) return;
|
||||
obj->spec_attr->scrollbar_mode = mode;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(dir != obj->spec_attr->scroll_dir) {
|
||||
obj->spec_attr->scroll_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_x = align;
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_y = align;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return (lv_scrollbar_mode_t) obj->spec_attr->scrollbar_mode;
|
||||
else return LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
|
||||
lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return (lv_dir_t) obj->spec_attr->scroll_dir;
|
||||
else return LV_DIR_ALL;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return (lv_scroll_snap_t) obj->spec_attr->scroll_snap_x;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return (lv_scroll_snap_t) obj->spec_attr->scroll_snap_y;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_top(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_bottom(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
int32_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
const lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
|
||||
int32_t tmp_y = child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_PART_MAIN);
|
||||
child_res = LV_MAX(child_res, tmp_y);
|
||||
}
|
||||
|
||||
int32_t space_top = lv_obj_get_style_space_top(obj, LV_PART_MAIN);
|
||||
int32_t space_bottom = lv_obj_get_style_space_bottom(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.y2 - space_bottom);
|
||||
}
|
||||
|
||||
int32_t self_h = lv_obj_get_self_height(obj);
|
||||
self_h = self_h - (lv_obj_get_height(obj) - space_top - space_bottom);
|
||||
self_h -= lv_obj_get_scroll_y(obj);
|
||||
return LV_MAX(child_res, self_h);
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_left(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*Normally can't scroll the object out on the left.
|
||||
*So simply use the current scroll position as "left size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With RTL base direction scrolling the left is normal so find the left most coordinate*/
|
||||
int32_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN);
|
||||
int32_t space_left = lv_obj_get_style_space_left(obj, LV_PART_MAIN);
|
||||
|
||||
int32_t child_res = 0;
|
||||
|
||||
uint32_t i;
|
||||
int32_t x1 = LV_COORD_MAX;
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
const lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
|
||||
int32_t tmp_x = child->coords.x1 - lv_obj_get_style_margin_left(child, LV_PART_MAIN);
|
||||
x1 = LV_MIN(x1, tmp_x);
|
||||
}
|
||||
|
||||
if(x1 != LV_COORD_MAX) {
|
||||
child_res = x1;
|
||||
child_res = (obj->coords.x1 + space_left) - child_res;
|
||||
}
|
||||
else {
|
||||
child_res = LV_COORD_MIN;
|
||||
}
|
||||
|
||||
int32_t self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - space_right - space_left);
|
||||
self_w += lv_obj_get_scroll_x(obj);
|
||||
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_scroll_right(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*With RTL base dir can't scroll to the object out on the right.
|
||||
*So simply use the current scroll position as "right size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/
|
||||
int32_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
const lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
|
||||
int32_t tmp_x = child->coords.x2 + lv_obj_get_style_margin_right(child, LV_PART_MAIN);
|
||||
child_res = LV_MAX(child_res, tmp_x);
|
||||
}
|
||||
|
||||
int32_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN);
|
||||
int32_t space_left = lv_obj_get_style_space_left(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.x2 - space_right);
|
||||
}
|
||||
|
||||
int32_t self_w;
|
||||
self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - space_right - space_left);
|
||||
self_w -= lv_obj_get_scroll_x(obj);
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end)
|
||||
{
|
||||
lv_anim_t * a;
|
||||
a = lv_anim_get(obj, scroll_x_anim);
|
||||
end->x = a ? -a->end_value : lv_obj_get_scroll_x(obj);
|
||||
|
||||
a = lv_anim_get(obj, scroll_y_anim);
|
||||
end->y = a ? -a->end_value : lv_obj_get_scroll_y(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_scroll_by_bounded(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(dx == 0 && dy == 0) return;
|
||||
|
||||
/*We need to know the final sizes for bound check*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
/*Don't let scroll more than naturally possible by the size of the content*/
|
||||
int32_t x_current = -lv_obj_get_scroll_x(obj);
|
||||
int32_t x_bounded = x_current + dx;
|
||||
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(x_bounded > 0) x_bounded = 0;
|
||||
if(x_bounded < 0) {
|
||||
int32_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x_bounded < -scroll_max) x_bounded = -scroll_max;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(x_bounded < 0) x_bounded = 0;
|
||||
if(x_bounded > 0) {
|
||||
int32_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x_bounded > scroll_max) x_bounded = scroll_max;
|
||||
}
|
||||
}
|
||||
|
||||
/*Don't let scroll more than naturally possible by the size of the content*/
|
||||
int32_t y_current = -lv_obj_get_scroll_y(obj);
|
||||
int32_t y_bounded = y_current + dy;
|
||||
|
||||
if(y_bounded > 0) y_bounded = 0;
|
||||
if(y_bounded < 0) {
|
||||
int32_t scroll_max = lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
if(y_bounded < -scroll_max) y_bounded = -scroll_max;
|
||||
}
|
||||
|
||||
dx = x_bounded - x_current;
|
||||
dy = y_bounded - y_current;
|
||||
if(dx || dy) {
|
||||
lv_obj_scroll_by(obj, dx, dy, anim_en);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scroll_by(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(dx == 0 && dy == 0) return;
|
||||
if(anim_en) {
|
||||
lv_display_t * d = lv_obj_get_display(obj);
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_deleted_cb(&a, scroll_end_cb);
|
||||
|
||||
if(dx) {
|
||||
uint32_t t = lv_anim_speed_clamped((lv_display_get_horizontal_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN,
|
||||
SCROLL_ANIM_TIME_MAX);
|
||||
lv_anim_set_duration(&a, t);
|
||||
int32_t sx = lv_obj_get_scroll_x(obj);
|
||||
lv_anim_set_values(&a, -sx, -sx + dx);
|
||||
lv_anim_set_exec_cb(&a, scroll_x_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_result_t res;
|
||||
res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
if(dy) {
|
||||
uint32_t t = lv_anim_speed_clamped((lv_display_get_vertical_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN,
|
||||
SCROLL_ANIM_TIME_MAX);
|
||||
lv_anim_set_duration(&a, t);
|
||||
int32_t sy = lv_obj_get_scroll_y(obj);
|
||||
lv_anim_set_values(&a, -sy, -sy + dy);
|
||||
lv_anim_set_exec_cb(&a, scroll_y_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_result_t res;
|
||||
res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Remove pending animations*/
|
||||
lv_anim_delete(obj, scroll_y_anim);
|
||||
lv_anim_delete(obj, scroll_x_anim);
|
||||
|
||||
lv_result_t res;
|
||||
res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
|
||||
res = lv_obj_scroll_by_raw(obj, dx, dy);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
|
||||
res = lv_obj_send_event(obj, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RESULT_OK) return;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_scroll_to_x(obj, x, anim_en);
|
||||
lv_obj_scroll_to_y(obj, y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_x(lv_obj_t * obj, int32_t x, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_delete(obj, scroll_x_anim);
|
||||
|
||||
int32_t scroll_x = lv_obj_get_scroll_x(obj);
|
||||
int32_t diff = -x + scroll_x;
|
||||
|
||||
lv_obj_scroll_by_bounded(obj, diff, 0, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_y(lv_obj_t * obj, int32_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_delete(obj, scroll_y_anim);
|
||||
|
||||
int32_t scroll_y = lv_obj_get_scroll_y(obj);
|
||||
int32_t diff = -y + scroll_y;
|
||||
|
||||
lv_obj_scroll_by_bounded(obj, 0, diff, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
scroll_area_into_view(&obj->coords, obj, &p, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
lv_obj_t * child = obj;
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
while(parent) {
|
||||
scroll_area_into_view(&obj->coords, child, &p, anim_en);
|
||||
child = parent;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
lv_result_t lv_obj_scroll_by_raw(lv_obj_t * obj, int32_t x, int32_t y)
|
||||
{
|
||||
if(x == 0 && y == 0) return LV_RESULT_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_result_t res = lv_obj_send_event(obj, LV_EVENT_SCROLL, NULL);
|
||||
if(res != LV_RESULT_OK) return res;
|
||||
lv_obj_invalidate(obj);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
bool lv_obj_is_scrolling(const lv_obj_t * obj)
|
||||
{
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) return true;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(lv_anim_get((lv_obj_t *)obj, scroll_x_anim) != NULL ||
|
||||
lv_anim_get((lv_obj_t *)obj, scroll_y_anim) != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lv_obj_stop_scroll_anim(const lv_obj_t * obj)
|
||||
{
|
||||
lv_anim_delete((lv_obj_t *)obj, scroll_y_anim);
|
||||
lv_anim_delete((lv_obj_t *)obj, scroll_x_anim);
|
||||
}
|
||||
|
||||
void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_update_layout(obj);
|
||||
lv_point_t p;
|
||||
lv_indev_scroll_get_snap_dist(obj, &p);
|
||||
if(p.x == LV_COORD_MAX || p.x == LV_COORD_MIN) p.x = 0;
|
||||
if(p.y == LV_COORD_MAX || p.y == LV_COORD_MIN) p.y = 0;
|
||||
lv_obj_scroll_by(obj, p.x, p.y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_area)
|
||||
{
|
||||
lv_area_set(hor_area, 0, 0, -1, -1);
|
||||
lv_area_set(ver_area, 0, 0, -1, -1);
|
||||
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) == false) return;
|
||||
|
||||
lv_scrollbar_mode_t sm = lv_obj_get_scrollbar_mode(obj);
|
||||
if(sm == LV_SCROLLBAR_MODE_OFF) return;
|
||||
|
||||
/*If there is no indev scrolling this object but `mode==active` return*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
if(sm == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) break;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
if(indev == NULL) return;
|
||||
}
|
||||
|
||||
int32_t st = lv_obj_get_scroll_top(obj);
|
||||
int32_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
int32_t sl = lv_obj_get_scroll_left(obj);
|
||||
int32_t sr = lv_obj_get_scroll_right(obj);
|
||||
|
||||
lv_dir_t dir = lv_obj_get_scroll_dir(obj);
|
||||
|
||||
bool ver_draw = false;
|
||||
if((dir & LV_DIR_VER) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_VER))) {
|
||||
ver_draw = true;
|
||||
}
|
||||
|
||||
bool hor_draw = false;
|
||||
if((dir & LV_DIR_HOR) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_HOR))) {
|
||||
hor_draw = true;
|
||||
}
|
||||
|
||||
if(!hor_draw && !ver_draw) return;
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL;
|
||||
|
||||
int32_t top_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR);
|
||||
int32_t bottom_space = lv_obj_get_style_pad_bottom(obj, LV_PART_SCROLLBAR);
|
||||
int32_t left_space = lv_obj_get_style_pad_left(obj, LV_PART_SCROLLBAR);
|
||||
int32_t right_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR);
|
||||
int32_t thickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR);
|
||||
int32_t length = lv_obj_get_style_length(obj, LV_PART_SCROLLBAR);
|
||||
|
||||
int32_t obj_h = lv_obj_get_height(obj);
|
||||
int32_t obj_w = lv_obj_get_width(obj);
|
||||
|
||||
/*Space required for the vertical and horizontal scrollbars*/
|
||||
int32_t ver_reg_space = ver_draw ? thickness : 0;
|
||||
int32_t hor_req_space = hor_draw ? thickness : 0;
|
||||
int32_t rem;
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR) <= LV_OPA_MIN &&
|
||||
lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR) <= LV_OPA_MIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Draw vertical scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
int32_t content_h = obj_h + st + sb;
|
||||
if(ver_draw && content_h) {
|
||||
ver_area->y1 = obj->coords.y1;
|
||||
ver_area->y2 = obj->coords.y2;
|
||||
if(rtl) {
|
||||
ver_area->x1 = obj->coords.x1 + left_space;
|
||||
ver_area->x2 = ver_area->x1 + thickness - 1;
|
||||
}
|
||||
else {
|
||||
ver_area->x2 = obj->coords.x2 - right_space;
|
||||
ver_area->x1 = ver_area->x2 - thickness + 1;
|
||||
}
|
||||
|
||||
int32_t sb_h = ((obj_h - top_space - bottom_space - hor_req_space) * obj_h) / content_h;
|
||||
sb_h = LV_MAX(length > 0 ? length : sb_h, SCROLLBAR_MIN_SIZE); /*Style-defined size, calculated size, or minimum size*/
|
||||
sb_h = LV_MIN(sb_h, obj_h); /*Limit scrollbar length to parent height*/
|
||||
rem = (obj_h - top_space - bottom_space - hor_req_space) -
|
||||
sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
int32_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_h <= 0) {
|
||||
ver_area->y1 = obj->coords.y1 + top_space;
|
||||
ver_area->y2 = obj->coords.y2 - bottom_space - hor_req_space - 1;
|
||||
}
|
||||
else {
|
||||
int32_t sb_y = (rem * sb) / scroll_h;
|
||||
sb_y = rem - sb_y;
|
||||
|
||||
ver_area->y1 = obj->coords.y1 + sb_y + top_space;
|
||||
ver_area->y2 = ver_area->y1 + sb_h - 1;
|
||||
if(ver_area->y1 < obj->coords.y1 + top_space) {
|
||||
ver_area->y1 = obj->coords.y1 + top_space;
|
||||
if(ver_area->y1 + SCROLLBAR_MIN_SIZE > ver_area->y2) {
|
||||
ver_area->y2 = ver_area->y1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(ver_area->y2 > obj->coords.y2 - hor_req_space - bottom_space) {
|
||||
ver_area->y2 = obj->coords.y2 - hor_req_space - bottom_space;
|
||||
if(ver_area->y2 - SCROLLBAR_MIN_SIZE < ver_area->y1) {
|
||||
ver_area->y1 = ver_area->y2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
int32_t content_w = obj_w + sl + sr;
|
||||
if(hor_draw && content_w) {
|
||||
hor_area->y2 = obj->coords.y2 - bottom_space;
|
||||
hor_area->y1 = hor_area->y2 - thickness + 1;
|
||||
hor_area->x1 = obj->coords.x1;
|
||||
hor_area->x2 = obj->coords.x2;
|
||||
|
||||
int32_t sb_w = ((obj_w - left_space - right_space - ver_reg_space) * obj_w) / content_w;
|
||||
sb_w = LV_MAX(length > 0 ? length : sb_w, SCROLLBAR_MIN_SIZE); /*Style-defined size, calculated size, or minimum size*/
|
||||
sb_w = LV_MIN(sb_w, obj_w); /*Limit scrollbar length to parent width*/
|
||||
rem = (obj_w - left_space - right_space - ver_reg_space) -
|
||||
sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
int32_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_w <= 0) {
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space + ver_reg_space - 1;
|
||||
hor_area->x2 = obj->coords.x2 - right_space;
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + left_space;
|
||||
hor_area->x2 = obj->coords.x2 - right_space - ver_reg_space - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int32_t sb_x = (rem * sr) / scroll_w;
|
||||
sb_x = rem - sb_x;
|
||||
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + left_space + ver_reg_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + left_space + ver_reg_space) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space + ver_reg_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) {
|
||||
hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - right_space) {
|
||||
hor_area->x2 = obj->coords.x2 - right_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) {
|
||||
hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + left_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + left_space) {
|
||||
hor_area->x1 = obj->coords.x1 + left_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) {
|
||||
hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - ver_reg_space - right_space) {
|
||||
hor_area->x2 = obj->coords.x2 - ver_reg_space - right_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) {
|
||||
hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scrollbar_invalidate(lv_obj_t * obj)
|
||||
{
|
||||
lv_area_t hor_area;
|
||||
lv_area_t ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
|
||||
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) lv_obj_invalidate_area(obj, &hor_area);
|
||||
if(lv_area_get_size(&ver_area) > 0) lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the bottom side is not remains scrolled in*/
|
||||
/*With snapping the content can't be scrolled in*/
|
||||
if(lv_obj_get_scroll_snap_y(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
int32_t st = lv_obj_get_scroll_top(obj);
|
||||
int32_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
if(sb < 0 && st > 0) {
|
||||
sb = LV_MIN(st, -sb);
|
||||
lv_obj_scroll_by(obj, 0, sb, anim_en);
|
||||
}
|
||||
}
|
||||
|
||||
if(lv_obj_get_scroll_snap_x(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
int32_t sl = lv_obj_get_scroll_left(obj);
|
||||
int32_t sr = lv_obj_get_scroll_right(obj);
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
/*Be sure the left side is not remains scrolled in*/
|
||||
if(sr < 0 && sl > 0) {
|
||||
sr = LV_MIN(sl, -sr);
|
||||
lv_obj_scroll_by(obj, sr, 0, anim_en);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Be sure the right side is not remains scrolled in*/
|
||||
if(sl < 0 && sr > 0) {
|
||||
sr = LV_MIN(sr, -sl);
|
||||
lv_obj_scroll_by(obj, sl, 0, anim_en);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void scroll_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0);
|
||||
}
|
||||
|
||||
static void scroll_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj));
|
||||
}
|
||||
|
||||
static void scroll_end_cb(lv_anim_t * a)
|
||||
{
|
||||
/*Do not sent END event if there wasn't a BEGIN*/
|
||||
if(a->start_cb_called) lv_obj_send_event(a->var, LV_EVENT_SCROLL_END, NULL);
|
||||
}
|
||||
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
if(!lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE)) return;
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(parent);
|
||||
int32_t snap_goal = 0;
|
||||
int32_t act = 0;
|
||||
const lv_area_t * area_tmp;
|
||||
|
||||
int32_t y_scroll = 0;
|
||||
lv_scroll_snap_t snap_y = lv_obj_get_scroll_snap_y(parent);
|
||||
if(snap_y != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
int32_t stop = lv_obj_get_style_space_top(parent, LV_PART_MAIN);
|
||||
int32_t sbottom = lv_obj_get_style_space_bottom(parent, LV_PART_MAIN);
|
||||
int32_t top_diff = parent->coords.y1 + stop - area_tmp->y1 - scroll_value->y;
|
||||
int32_t bottom_diff = -(parent->coords.y2 - sbottom - area_tmp->y2 - scroll_value->y);
|
||||
int32_t parent_h = lv_obj_get_height(parent) - stop - sbottom;
|
||||
if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0;
|
||||
else if(top_diff > 0) {
|
||||
y_scroll = top_diff;
|
||||
/*Do not let scrolling in*/
|
||||
int32_t st = lv_obj_get_scroll_top(parent);
|
||||
if(st - y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
else if(bottom_diff > 0) {
|
||||
y_scroll = -bottom_diff;
|
||||
/*Do not let scrolling in*/
|
||||
int32_t sb = lv_obj_get_scroll_bottom(parent);
|
||||
if(sb + y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
|
||||
switch(snap_y) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.y1 + stop;
|
||||
act = area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.y2 - sbottom;
|
||||
act = area_tmp->y2 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.y1 + stop + parent_h / 2;
|
||||
act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t x_scroll = 0;
|
||||
lv_scroll_snap_t snap_x = lv_obj_get_scroll_snap_x(parent);
|
||||
if(snap_x != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
int32_t sleft = lv_obj_get_style_space_left(parent, LV_PART_MAIN);
|
||||
int32_t sright = lv_obj_get_style_space_right(parent, LV_PART_MAIN);
|
||||
int32_t left_diff = parent->coords.x1 + sleft - area_tmp->x1 - scroll_value->x;
|
||||
int32_t right_diff = -(parent->coords.x2 - sright - area_tmp->x2 - scroll_value->x);
|
||||
if((left_diff >= 0 && right_diff >= 0)) x_scroll = 0;
|
||||
else if(left_diff > 0) {
|
||||
x_scroll = left_diff;
|
||||
/*Do not let scrolling in*/
|
||||
int32_t sl = lv_obj_get_scroll_left(parent);
|
||||
if(sl - x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
else if(right_diff > 0) {
|
||||
x_scroll = -right_diff;
|
||||
/*Do not let scrolling in*/
|
||||
int32_t sr = lv_obj_get_scroll_right(parent);
|
||||
if(sr + x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
|
||||
int32_t parent_w = lv_obj_get_width(parent) - sleft - sright;
|
||||
switch(snap_x) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.x1 + sleft;
|
||||
act = area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.x2 - sright;
|
||||
act = area_tmp->x2 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.x1 + sleft + parent_w / 2;
|
||||
act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
/*Remove any pending scroll animations.*/
|
||||
lv_anim_delete(parent, scroll_y_anim);
|
||||
lv_anim_delete(parent, scroll_x_anim);
|
||||
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && x_scroll < 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && x_scroll > 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && y_scroll < 0) y_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && y_scroll > 0) y_scroll = 0;
|
||||
|
||||
scroll_value->x += anim_en ? x_scroll : 0;
|
||||
scroll_value->y += anim_en ? y_scroll : 0;
|
||||
lv_obj_scroll_by(parent, x_scroll, y_scroll, anim_en);
|
||||
}
|
||||
301
inc/lvgl/src/core/lv_obj_scroll.h
Normal file
301
inc/lvgl/src/core/lv_obj_scroll.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_SCROLL_H
|
||||
#define LV_OBJ_SCROLL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
|
||||
/** Scrollbar modes: shows when should the scrollbars be visible*/
|
||||
typedef enum {
|
||||
LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/
|
||||
LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/
|
||||
LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when Widget is being scrolled*/
|
||||
LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/
|
||||
} lv_scrollbar_mode_t;
|
||||
|
||||
/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/
|
||||
typedef enum {
|
||||
LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/
|
||||
LV_SCROLL_SNAP_START, /**< Align to the left/top*/
|
||||
LV_SCROLL_SNAP_END, /**< Align to the right/bottom*/
|
||||
LV_SCROLL_SNAP_CENTER /**< Align to the center*/
|
||||
} lv_scroll_snap_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set how the scrollbars should behave.
|
||||
* @param obj pointer to Widget
|
||||
* @param mode LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE
|
||||
*/
|
||||
void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode);
|
||||
|
||||
/**
|
||||
* Set direction Widget can be scrolled
|
||||
* @param obj pointer to Widget
|
||||
* @param dir one or more bit-wise OR-ed values of `lv_dir_t` enumeration
|
||||
*/
|
||||
void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir);
|
||||
|
||||
/**
|
||||
* Set where to snap the children when scrolling ends horizontally
|
||||
* @param obj pointer to Widget
|
||||
* @param align value from `lv_scroll_snap_t` enumeration
|
||||
*/
|
||||
void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align);
|
||||
|
||||
/**
|
||||
* Set where to snap the children when scrolling ends vertically
|
||||
* @param obj pointer to Widget
|
||||
* @param align value from `lv_scroll_snap_t` enumeration
|
||||
*/
|
||||
void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current scroll mode (when to hide the scrollbars)
|
||||
* @param obj pointer to Widget
|
||||
* @return the current scroll mode from `lv_scrollbar_mode_t`
|
||||
*/
|
||||
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get directions Widget can be scrolled (set with `lv_obj_set_scroll_dir()`)
|
||||
* @param obj pointer to Widget
|
||||
* @return current scroll direction bit(s)
|
||||
*/
|
||||
lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get where to snap child Widgets when horizontal scrolling ends.
|
||||
* @param obj pointer to Widget
|
||||
* @return current snap value from `lv_scroll_snap_t`
|
||||
*/
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get where to snap child Widgets when vertical scrolling ends.
|
||||
* @param obj pointer to Widget
|
||||
* @return current snap value from `lv_scroll_snap_t`
|
||||
*/
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get current X scroll position. Identical to `lv_obj_get_scroll_left()`.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return current scroll position from left edge
|
||||
* - If Widget is not scrolled return 0.
|
||||
* - If scrolled return > 0.
|
||||
* - If scrolled inside (elastic scroll) return < 0.
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_x(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get current Y scroll position. Identical to `lv_obj_get_scroll_top()`.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return current scroll position from top edge
|
||||
* - If Widget is not scrolled return 0.
|
||||
* - If scrolled return > 0.
|
||||
* - If scrolled inside (elastic scroll) return < 0.
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_y(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Number of pixels a scrollable container Widget can be scrolled down
|
||||
* before its top edge appears. When LV_OBJ_FLAG_SCROLL_ELASTIC flag
|
||||
* is set in Widget, this value can go negative while Widget is being
|
||||
* dragged below its normal top-edge boundary.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return pixels Widget can be scrolled down before its top edge appears
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_top(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Number of pixels a scrollable container Widget can be scrolled up
|
||||
* before its bottom edge appears. When LV_OBJ_FLAG_SCROLL_ELASTIC flag
|
||||
* is set in Widget, this value can go negative while Widget is being
|
||||
* dragged above its normal bottom-edge boundary.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return pixels Widget can be scrolled up before its bottom edge appears
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_bottom(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Number of pixels a scrollable container Widget can be scrolled right
|
||||
* before its left edge appears. When LV_OBJ_FLAG_SCROLL_ELASTIC flag
|
||||
* is set in Widget, this value can go negative while Widget is being
|
||||
* dragged farther right than its normal left-edge boundary.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return pixels Widget can be scrolled right before its left edge appears
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_left(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Number of pixels a scrollable container Widget can be scrolled left
|
||||
* before its right edge appears. When LV_OBJ_FLAG_SCROLL_ELASTIC flag
|
||||
* is set in Widget, this value can go negative while Widget is being
|
||||
* dragged farther left than its normal right-edge boundary.
|
||||
* @param obj pointer to scrollable container Widget
|
||||
* @return pixels Widget can be scrolled left before its right edge appears
|
||||
*/
|
||||
int32_t lv_obj_get_scroll_right(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the X and Y coordinates where the scrolling will end for Widget if a scrolling animation is in progress.
|
||||
* If no scrolling animation, give the current `x` or `y` scroll position.
|
||||
* @param obj pointer to scrollable Widget
|
||||
* @param end pointer to `lv_point_t` object in which to store result
|
||||
*/
|
||||
void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Scroll by given amount of pixels.
|
||||
* @param obj pointer to scrollable Widget to scroll
|
||||
* @param dx pixels to scroll horizontally
|
||||
* @param dy pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
* @note > 0 value means scroll right/bottom (show the more content on the right/bottom)
|
||||
* @note e.g. dy = -20 means scroll down 20 px
|
||||
*/
|
||||
void lv_obj_scroll_by(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll by given amount of pixels.
|
||||
* `dx` and `dy` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to scrollable Widget to scroll
|
||||
* @param dx pixels to scroll horizontally
|
||||
* @param dy pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
* @note e.g. dy = -20 means scroll down 20 px
|
||||
*/
|
||||
void lv_obj_scroll_by_bounded(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to given coordinate on Widget.
|
||||
* `x` and `y` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to scrollable Widget to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param y pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to X coordinate on Widget.
|
||||
* `x` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to scrollable Widget to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_x(lv_obj_t * obj, int32_t x, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to Y coordinate on Widget.
|
||||
* `y` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to scrollable Widget to scroll
|
||||
* @param y pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_y(lv_obj_t * obj, int32_t y, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll `obj`'s parent Widget until `obj` becomes visible.
|
||||
* @param obj pointer to Widget to scroll into view
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll `obj`'s parent Widgets recursively until `obj` becomes visible.
|
||||
* Widget will be scrolled into view even it has nested scrollable parents.
|
||||
* @param obj pointer to Widget to scroll into view
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Tell whether Widget is being scrolled or not at this moment
|
||||
* @param obj pointer to Widget
|
||||
* @return true: `obj` is being scrolled
|
||||
*/
|
||||
bool lv_obj_is_scrolling(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Stop scrolling the current object
|
||||
*
|
||||
* @param obj The object being scrolled
|
||||
*/
|
||||
void lv_obj_stop_scroll_anim(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check children of `obj` and scroll `obj` to fulfill scroll_snap settings.
|
||||
* @param obj Widget whose children need to be checked and snapped
|
||||
* @param anim_en LV_ANIM_ON/OFF
|
||||
*/
|
||||
void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Get the area of the scrollbars
|
||||
* @param obj pointer to Widget
|
||||
* @param hor pointer to store the area of the horizontal scrollbar
|
||||
* @param ver pointer to store the area of the vertical scrollbar
|
||||
*/
|
||||
void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver);
|
||||
|
||||
/**
|
||||
* Invalidate the area of the scrollbars
|
||||
* @param obj pointer to Widget
|
||||
*/
|
||||
void lv_obj_scrollbar_invalidate(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Checks if the content is scrolled "in" and adjusts it to a normal position.
|
||||
* @param obj pointer to Widget
|
||||
* @param anim_en LV_ANIM_ON/OFF
|
||||
*/
|
||||
void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_SCROLL_H*/
|
||||
50
inc/lvgl/src/core/lv_obj_scroll_private.h
Normal file
50
inc/lvgl/src/core/lv_obj_scroll_private.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file lv_obj_scroll_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_SCROLL_PRIVATE_H
|
||||
#define LV_OBJ_SCROLL_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_obj_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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_RESULT_INVALID`: to object was deleted in `LV_EVENT_SCROLL`;
|
||||
* `LV_RESULT_OK`: if the object is still valid
|
||||
*/
|
||||
lv_result_t lv_obj_scroll_by_raw(lv_obj_t * obj, int32_t x, int32_t y);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_SCROLL_PRIVATE_H*/
|
||||
1345
inc/lvgl/src/core/lv_obj_style.c
Normal file
1345
inc/lvgl/src/core/lv_obj_style.c
Normal file
File diff suppressed because it is too large
Load Diff
443
inc/lvgl/src/core/lv_obj_style.h
Normal file
443
inc/lvgl/src/core/lv_obj_style.h
Normal file
@@ -0,0 +1,443 @@
|
||||
/**
|
||||
* @file lv_obj_style.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_STYLE_H
|
||||
#define LV_OBJ_STYLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Possible states of a widget.
|
||||
* OR-ed values are possible
|
||||
*/
|
||||
typedef enum {
|
||||
LV_STATE_DEFAULT = 0,
|
||||
LV_STATE_ALT = 1 << 0,
|
||||
/*1 reserved*/
|
||||
LV_STATE_CHECKED = 1 << 2,
|
||||
LV_STATE_FOCUSED = 1 << 3,
|
||||
LV_STATE_FOCUS_KEY = 1 << 4,
|
||||
LV_STATE_EDITED = 1 << 5,
|
||||
LV_STATE_HOVERED = 1 << 6,
|
||||
LV_STATE_PRESSED = 1 << 7,
|
||||
LV_STATE_SCROLLED = 1 << 8,
|
||||
LV_STATE_DISABLED = 1 << 9,
|
||||
/*2 reserved*/
|
||||
LV_STATE_USER_1 = 1 << 12,
|
||||
LV_STATE_USER_2 = 1 << 13,
|
||||
LV_STATE_USER_3 = 1 << 14,
|
||||
LV_STATE_USER_4 = 1 << 15,
|
||||
|
||||
LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/
|
||||
} 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
|
||||
* Not all parts are used by every widget
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
LV_PART_MAIN = 0x000000, /**< A background like rectangle*/
|
||||
LV_PART_SCROLLBAR = 0x010000, /**< The scrollbar(s)*/
|
||||
LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/
|
||||
LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/
|
||||
LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/
|
||||
LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/
|
||||
LV_PART_CURSOR = 0x060000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/
|
||||
|
||||
LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/
|
||||
|
||||
LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/
|
||||
} lv_part_t;
|
||||
|
||||
typedef enum {
|
||||
LV_STYLE_STATE_CMP_SAME, /**< The style properties in the 2 states are identical */
|
||||
LV_STYLE_STATE_CMP_DIFF_REDRAW, /**< The differences can be shown with a simple redraw */
|
||||
LV_STYLE_STATE_CMP_DIFF_DRAW_PAD, /**< The differences can be shown with a simple redraw */
|
||||
LV_STYLE_STATE_CMP_DIFF_LAYOUT, /**< The differences can be shown with a simple redraw */
|
||||
} lv_style_state_cmp_t;
|
||||
|
||||
/**
|
||||
* A joint type for `lv_part_t` and `lv_state_t`. Example values
|
||||
* - `0`: means `LV_PART_MAIN | LV_STATE_DEFAULT`
|
||||
* - `LV_STATE_PRSSED`
|
||||
* - `LV_PART_KNOB`
|
||||
* - `LV_PART_KNOB | LV_STATE_PRESSED | LV_STATE_CHECKED`
|
||||
*/
|
||||
typedef uint32_t lv_style_selector_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Add a style to an object.
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style to add
|
||||
* @param selector OR-ed value of parts and state to which the style should be added
|
||||
*
|
||||
* Examples:
|
||||
* @code
|
||||
* lv_obj_add_style(btn, &style_btn, 0); //Default button style
|
||||
*
|
||||
* lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed
|
||||
* @endcode
|
||||
*/
|
||||
void lv_obj_add_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Replaces a style of an object, preserving the order of the style stack (local styles and transitions are ignored).
|
||||
* @param obj pointer to an object
|
||||
* @param old_style pointer to a style to replace.
|
||||
* @param new_style pointer to a style to replace the old style with.
|
||||
* @param selector OR-ed values of states and a part to replace only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used
|
||||
*
|
||||
* Examples:
|
||||
* @code
|
||||
* lv_obj_replace_style(obj, &yellow_style, &blue_style, LV_PART_ANY | LV_STATE_ANY); //Replace a specific style
|
||||
*
|
||||
* lv_obj_replace_style(obj, &yellow_style, &blue_style, LV_PART_MAIN | LV_STATE_PRESSED); //Replace a specific style assigned to the main part when it is pressed
|
||||
* @endcode
|
||||
*/
|
||||
bool lv_obj_replace_style(lv_obj_t * obj, const lv_style_t * old_style, const lv_style_t * new_style,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Remove a style from an object.
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style to remove. Can be NULL to check only the selector
|
||||
* @param selector OR-ed values of states and a part to remove only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used
|
||||
*
|
||||
* Examples:
|
||||
* @code
|
||||
* lv_obj_remove_style(obj, &style, LV_PART_ANY | LV_STATE_ANY); //Remove a specific style
|
||||
*
|
||||
* lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part
|
||||
*
|
||||
* lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles
|
||||
* @endcode
|
||||
*/
|
||||
void lv_obj_remove_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
|
||||
/**
|
||||
* Remove all styles added by a theme from a widget
|
||||
* @param selector OR-ed values of states and a part to remove only styles with matching selectors.
|
||||
* LV_STATE_ANY and LV_PART_ANY can be used
|
||||
* @param obj pointer to a widget
|
||||
*/
|
||||
void lv_obj_remove_theme(lv_obj_t * obj, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Remove all styles from an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_remove_style_all(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Notify all object if a style is modified
|
||||
* @param style pointer to a style. Only the objects with this style will be notified
|
||||
* (NULL to notify all objects)
|
||||
*/
|
||||
void lv_obj_report_style_change(lv_style_t * style);
|
||||
|
||||
/**
|
||||
* Notify an object and its children about its style is modified.
|
||||
* @param obj pointer to an object
|
||||
* @param part the part whose style was changed. E.g. `LV_PART_ANY`, `LV_PART_MAIN`
|
||||
* @param prop `LV_STYLE_PROP_ANY` or an `LV_STYLE_...` property.
|
||||
* It is used to optimize what needs to be refreshed.
|
||||
* `LV_STYLE_PROP_INV` to perform only a style cache update
|
||||
*/
|
||||
void lv_obj_refresh_style(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* Temporary disable a style for a selector. It will look like is the style wasn't added
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style
|
||||
* @param selector the selector of a style (e.g. LV_STATE_PRESSED | LV_PART_KNOB)
|
||||
* @param dis true: disable the style, false: enable the style
|
||||
*/
|
||||
void lv_obj_style_set_disabled(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector, bool dis);
|
||||
|
||||
/**
|
||||
* Get if a given style is disabled on an object.
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style
|
||||
* @param selector the selector of a style (e.g. LV_STATE_PRESSED | LV_PART_KNOB)
|
||||
* @return true: disable the style, false: enable the style
|
||||
*/
|
||||
bool lv_obj_style_get_disabled(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Enable or disable automatic style refreshing when a new style is added/removed to/from an object
|
||||
* or any other style change happens.
|
||||
* @param en true: enable refreshing; false: disable refreshing
|
||||
*/
|
||||
void lv_obj_enable_style_refresh(bool en);
|
||||
|
||||
/**
|
||||
* Get the value of a style property. The current state of the object will be considered.
|
||||
* Inherited properties will be inherited.
|
||||
* If a property is not set a default value will be returned.
|
||||
* @param obj pointer to an object
|
||||
* @param part a part from which the property should be get
|
||||
* @param prop the property to get
|
||||
* @return the value of the property.
|
||||
* Should be read from the correct field of the `lv_style_value_t` according to the type of the property.
|
||||
*/
|
||||
lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* Check if an object has a specified style property for a given style selector.
|
||||
* @param obj pointer to an object
|
||||
* @param selector the style selector to be checked, defining the scope of the style to be examined.
|
||||
* @param prop the property to be checked.
|
||||
* @return true if the object has the specified selector and property, false otherwise.
|
||||
*/
|
||||
bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* Set local style property on an object's part and state.
|
||||
* @param obj pointer to an object
|
||||
* @param prop the property
|
||||
* @param value value of the property. The correct element should be set according to the type of the property
|
||||
* @param selector OR-ed value of parts and state for which the style should be set
|
||||
*/
|
||||
void lv_obj_set_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);
|
||||
|
||||
/**
|
||||
* Remove a local style property from a part of an object with a given state.
|
||||
* @param obj pointer to an object
|
||||
* @param prop a style property to remove.
|
||||
* @param selector OR-ed value of parts and state for which the style should be removed
|
||||
* @return true the property was found and removed; false: the property was not found
|
||||
*/
|
||||
bool lv_obj_remove_local_style_prop(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 lv_obj_t * obj, lv_part_t part, lv_style_value_t v);
|
||||
|
||||
/**
|
||||
* Fade in an an object and all its children.
|
||||
* @param obj the object to fade in
|
||||
* @param time time of fade
|
||||
* @param delay delay to start the animation
|
||||
*/
|
||||
void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay);
|
||||
|
||||
/**
|
||||
* Fade out an an object and all its children.
|
||||
* @param obj the object to fade out
|
||||
* @param time time of fade
|
||||
* @param delay delay to start the animation
|
||||
*/
|
||||
void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay);
|
||||
|
||||
static inline lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector)
|
||||
{
|
||||
return (lv_state_t)(selector & 0xFFFF);
|
||||
}
|
||||
|
||||
static inline lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
|
||||
{
|
||||
return (lv_part_t)(selector & 0xFF0000);
|
||||
}
|
||||
|
||||
#include "lv_obj_style_gen.h"
|
||||
|
||||
static inline void lv_obj_set_style_pad_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_left(obj, value, selector);
|
||||
lv_obj_set_style_pad_right(obj, value, selector);
|
||||
lv_obj_set_style_pad_top(obj, value, selector);
|
||||
lv_obj_set_style_pad_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_left(obj, value, selector);
|
||||
lv_obj_set_style_pad_right(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_top(obj, value, selector);
|
||||
lv_obj_set_style_pad_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_margin_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_margin_left(obj, value, selector);
|
||||
lv_obj_set_style_margin_right(obj, value, selector);
|
||||
lv_obj_set_style_margin_top(obj, value, selector);
|
||||
lv_obj_set_style_margin_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_margin_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_margin_left(obj, value, selector);
|
||||
lv_obj_set_style_margin_right(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_margin_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_margin_top(obj, value, selector);
|
||||
lv_obj_set_style_margin_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_row(obj, value, selector);
|
||||
lv_obj_set_style_pad_column(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_size(lv_obj_t * obj, int32_t width, int32_t height,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_width(obj, width, selector);
|
||||
lv_obj_set_style_height(obj, height, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_transform_scale(lv_obj_t * obj, int32_t value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_transform_scale_x(obj, value, selector);
|
||||
lv_obj_set_style_transform_scale_y(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline int32_t lv_obj_get_style_space_left(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t padding = lv_obj_get_style_pad_left(obj, part);
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, part);
|
||||
lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part);
|
||||
return (border_side & LV_BORDER_SIDE_LEFT) ? padding + border_width : padding;
|
||||
}
|
||||
|
||||
static inline int32_t lv_obj_get_style_space_right(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t padding = lv_obj_get_style_pad_right(obj, part);
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, part);
|
||||
lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part);
|
||||
return (border_side & LV_BORDER_SIDE_RIGHT) ? padding + border_width : padding;
|
||||
}
|
||||
|
||||
static inline int32_t lv_obj_get_style_space_top(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t padding = lv_obj_get_style_pad_top(obj, part);
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, part);
|
||||
lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part);
|
||||
return (border_side & LV_BORDER_SIDE_TOP) ? padding + border_width : padding;
|
||||
}
|
||||
|
||||
static inline int32_t lv_obj_get_style_space_bottom(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t padding = lv_obj_get_style_pad_bottom(obj, part);
|
||||
int32_t border_width = lv_obj_get_style_border_width(obj, part);
|
||||
lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part);
|
||||
return (border_side & LV_BORDER_SIDE_BOTTOM) ? padding + border_width : padding;
|
||||
}
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const lv_obj_t * obj, lv_part_t part, const char * txt);
|
||||
|
||||
static inline int32_t lv_obj_get_style_transform_scale_x_safe(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t scale = lv_obj_get_style_transform_scale_x(obj, part);
|
||||
return scale > 0 ? scale : 1;
|
||||
}
|
||||
|
||||
static inline int32_t lv_obj_get_style_transform_scale_y_safe(const lv_obj_t * obj, lv_part_t part)
|
||||
{
|
||||
int32_t scale = lv_obj_get_style_transform_scale_y(obj, part);
|
||||
return scale > 0 ? scale : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `opa` style property from all parents and multiply and `>> 8` them.
|
||||
* @param obj the object whose opacity should be get
|
||||
* @param part the part whose opacity should be get. Non-MAIN parts will consider the `opa` of the MAIN part too
|
||||
* @return the final opacity considering the parents' opacity too
|
||||
*/
|
||||
lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part);
|
||||
|
||||
|
||||
/**
|
||||
* Apply recolor effect to the input color based on the object's style properties.
|
||||
* @param obj the target object containing recolor style properties
|
||||
* @param part the part to retrieve recolor styles.
|
||||
* @param color the original color to be modified
|
||||
* @return the blended color after applying recolor and opacity
|
||||
*/
|
||||
lv_color32_t lv_obj_style_apply_recolor(const lv_obj_t * obj, lv_part_t part, lv_color32_t color);
|
||||
|
||||
/**
|
||||
* Get the `recolor` style property from all parents and blend them recursively.
|
||||
* @param obj the object whose recolor value should be retrieved
|
||||
* @param part the target part to check. Non-MAIN parts will also consider
|
||||
* the `recolor` value from the MAIN part during calculation
|
||||
* @return the final blended recolor value combining all parent's recolor values
|
||||
*/
|
||||
lv_color32_t lv_obj_get_style_recolor_recursive(const lv_obj_t * obj, lv_part_t part);
|
||||
|
||||
#if LV_USE_OBSERVER
|
||||
/**
|
||||
* Disable a style if a subject's value is not equal to a reference value
|
||||
* @param obj pointer to Widget
|
||||
* @param style pointer to a style
|
||||
* @param selector pointer to a selector
|
||||
* @param subject pointer to Subject
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector,
|
||||
lv_subject_t * subject, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Connect a subject's value to a style property of a widget.
|
||||
* @param obj pointer to a Widget
|
||||
* @param prop a style property
|
||||
* @param selector a selector for which the property should be added, e.g. `LV_PART_KNOB | LV_STATE_PRESSED`
|
||||
* @param subject pointer a Subject to which value the property should be bound
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector,
|
||||
lv_subject_t * subject);
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_STYLE_H*/
|
||||
1042
inc/lvgl/src/core/lv_obj_style_gen.c
Normal file
1042
inc/lvgl/src/core/lv_obj_style_gen.c
Normal file
File diff suppressed because it is too large
Load Diff
3572
inc/lvgl/src/core/lv_obj_style_gen.h
Normal file
3572
inc/lvgl/src/core/lv_obj_style_gen.h
Normal file
File diff suppressed because it is too large
Load Diff
97
inc/lvgl/src/core/lv_obj_style_private.h
Normal file
97
inc/lvgl/src/core/lv_obj_style_private.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file lv_obj_style_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_STYLE_PRIVATE_H
|
||||
#define LV_OBJ_STYLE_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_obj_style.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_style_t {
|
||||
const lv_style_t * style;
|
||||
uint32_t selector : 24;
|
||||
uint32_t is_local : 1;
|
||||
uint32_t is_trans : 1;
|
||||
uint32_t is_disabled : 1;
|
||||
uint32_t is_theme : 1; /**< The style is added by a theme */
|
||||
};
|
||||
|
||||
struct _lv_obj_style_transition_dsc_t {
|
||||
uint16_t time;
|
||||
uint16_t delay;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_prop_t prop;
|
||||
lv_anim_path_cb_t path_cb;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the object related style manager module.
|
||||
* Called by LVGL in `lv_init()`
|
||||
*/
|
||||
void lv_obj_style_init(void);
|
||||
|
||||
/**
|
||||
* Deinitialize the object related style manager module.
|
||||
* Called by LVGL in `lv_deinit()`
|
||||
*/
|
||||
void lv_obj_style_deinit(void);
|
||||
|
||||
/**
|
||||
* Used internally to create a style transition
|
||||
* @param obj
|
||||
* @param part
|
||||
* @param prev_state
|
||||
* @param new_state
|
||||
* @param tr
|
||||
*/
|
||||
void lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state,
|
||||
lv_state_t new_state, const lv_obj_style_transition_dsc_t * tr);
|
||||
|
||||
/**
|
||||
* Used internally to compare the appearance of an object in 2 states
|
||||
* @param obj
|
||||
* @param state1
|
||||
* @param state2
|
||||
* @return
|
||||
*/
|
||||
lv_style_state_cmp_t lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2);
|
||||
|
||||
/**
|
||||
* Update the layer type of a widget bayed on its current styles.
|
||||
* The result will be stored in `obj->spec_attr->layer_type`
|
||||
* @param obj the object whose layer should be updated
|
||||
*/
|
||||
void lv_obj_update_layer_type(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_STYLE_PRIVATE_H*/
|
||||
854
inc/lvgl/src/core/lv_obj_tree.c
Normal file
854
inc/lvgl/src/core/lv_obj_tree.c
Normal file
@@ -0,0 +1,854 @@
|
||||
/**
|
||||
* @file lv_obj_tree.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_private.h"
|
||||
#include "lv_obj_class_private.h"
|
||||
#include "../indev/lv_indev.h"
|
||||
#include "../indev/lv_indev_private.h"
|
||||
#include "../display/lv_display.h"
|
||||
#include "../display/lv_display_private.h"
|
||||
#include "../misc/lv_anim_private.h"
|
||||
#include "../misc/lv_async.h"
|
||||
#include "../core/lv_global.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_obj_class)
|
||||
#define disp_ll_p &(LV_GLOBAL_DEFAULT()->disp_ll)
|
||||
|
||||
#define OBJ_DUMP_STRING_LEN 128
|
||||
#define LV_OBJ_NAME_MAX_LEN 128
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_delete_async_cb(void * obj);
|
||||
static void obj_delete_core(lv_obj_t * obj);
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
static void dump_tree_core(lv_obj_t * obj, int32_t depth);
|
||||
static lv_obj_t * lv_obj_get_first_not_deleting_child(lv_obj_t * obj);
|
||||
#if LV_USE_OBJ_NAME
|
||||
static lv_obj_t * find_by_name_direct(const lv_obj_t * parent, const char * name, size_t len);
|
||||
#endif /*LV_USE_OBJ_NAME*/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_delete(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->is_deleting)
|
||||
return;
|
||||
|
||||
LV_LOG_TRACE("begin (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * par = lv_obj_get_parent(obj);
|
||||
|
||||
lv_display_t * disp = NULL;
|
||||
bool act_screen_del = false;
|
||||
if(par == NULL) {
|
||||
disp = lv_obj_get_display(obj);
|
||||
if(!disp) return; /*Shouldn't happen*/
|
||||
if(disp->act_scr == obj) act_screen_del = true;
|
||||
}
|
||||
|
||||
obj_delete_core(obj);
|
||||
|
||||
/*Call the ancestor's event handler to the parent to notify it about the child delete*/
|
||||
if(par && !par->is_deleting) {
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
lv_obj_send_event(par, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_obj_send_event(par, LV_EVENT_CHILD_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*Handle if the active screen was deleted*/
|
||||
if(act_screen_del) {
|
||||
LV_LOG_WARN("the active screen was deleted");
|
||||
disp->act_scr = NULL;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_clean(lv_obj_t * obj)
|
||||
{
|
||||
LV_LOG_TRACE("begin (clean %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
uint32_t cnt = lv_obj_get_child_count(obj);
|
||||
lv_obj_t * child = lv_obj_get_first_not_deleting_child(obj);
|
||||
while(child) {
|
||||
obj_delete_core(child);
|
||||
child = lv_obj_get_first_not_deleting_child(obj);
|
||||
}
|
||||
/*Just to remove scroll animations if any*/
|
||||
lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF);
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->scroll.x = 0;
|
||||
obj->spec_attr->scroll.y = 0;
|
||||
}
|
||||
|
||||
if(lv_obj_get_child_count(obj) < cnt) {
|
||||
lv_obj_send_event(obj, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_obj_send_event(obj, LV_EVENT_CHILD_DELETED, NULL);
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
LV_LOG_TRACE("finished (clean %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_delete_delayed(lv_obj_t * obj, uint32_t delay_ms)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_exec_cb(&a, NULL);
|
||||
lv_anim_set_duration(&a, 1);
|
||||
lv_anim_set_delay(&a, delay_ms);
|
||||
lv_anim_set_completed_cb(&a, lv_obj_delete_anim_completed_cb);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_delete_anim_completed_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_delete(a->var);
|
||||
}
|
||||
|
||||
void lv_obj_delete_async(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_async_call(lv_obj_delete_async_cb, obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
|
||||
if(obj->parent == NULL) {
|
||||
LV_LOG_WARN("Can't set the parent of a screen");
|
||||
return;
|
||||
}
|
||||
|
||||
if(parent == NULL) {
|
||||
LV_LOG_WARN("Can't set parent == NULL to an object");
|
||||
return;
|
||||
}
|
||||
|
||||
if(parent == obj->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
|
||||
lv_obj_t * old_parent = obj->parent;
|
||||
/*Remove the object from the old parent's child list*/
|
||||
int32_t i;
|
||||
for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_count(old_parent) - 2; i++) {
|
||||
old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1];
|
||||
}
|
||||
old_parent->spec_attr->child_cnt--;
|
||||
if(old_parent->spec_attr->child_cnt) {
|
||||
old_parent->spec_attr->children = lv_realloc(old_parent->spec_attr->children,
|
||||
old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
}
|
||||
else {
|
||||
lv_free(old_parent->spec_attr->children);
|
||||
old_parent->spec_attr->children = NULL;
|
||||
}
|
||||
|
||||
/*Add the child to the new parent as the last (newest child)*/
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_realloc(parent->spec_attr->children,
|
||||
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
parent->spec_attr->children[lv_obj_get_child_count(parent) - 1] = obj;
|
||||
|
||||
obj->parent = parent;
|
||||
|
||||
/*Notify the original parent because one of its children is lost*/
|
||||
lv_obj_scrollbar_invalidate(old_parent);
|
||||
lv_obj_send_event(old_parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_obj_send_event(old_parent, LV_EVENT_CHILD_DELETED, NULL);
|
||||
|
||||
/*Notify the new parent about the child*/
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, NULL);
|
||||
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_move_to_index(lv_obj_t * obj, int32_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/* Check parent validity */
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(!parent) {
|
||||
LV_LOG_WARN("parent is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t parent_child_count = lv_obj_get_child_count(parent);
|
||||
/* old_index only can be 0 or greater, this point cannot be reached if the parent is not null */
|
||||
const int32_t old_index = lv_obj_get_index(obj);
|
||||
LV_ASSERT(0 <= old_index);
|
||||
|
||||
if(index < 0) {
|
||||
index += parent_child_count;
|
||||
}
|
||||
|
||||
/* Index was negative and the absolute value is greater than parent child count */
|
||||
if((index < 0)
|
||||
/* Index is same or bigger than parent child count */
|
||||
|| (index >= (int32_t) parent_child_count)
|
||||
/* If both previous and new index are the same */
|
||||
|| (index == old_index)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t i = old_index;
|
||||
if(index < old_index) {
|
||||
while(i > index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i - 1];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(i < index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
parent->spec_attr->children[index] = obj;
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_obj_invalidate(parent);
|
||||
}
|
||||
|
||||
void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj1, MY_CLASS);
|
||||
LV_ASSERT_OBJ(obj2, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj1);
|
||||
lv_obj_t * parent2 = lv_obj_get_parent(obj2);
|
||||
|
||||
uint_fast32_t index1 = lv_obj_get_index(obj1);
|
||||
uint_fast32_t index2 = lv_obj_get_index(obj2);
|
||||
|
||||
lv_obj_send_event(parent2, LV_EVENT_CHILD_DELETED, obj2);
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_DELETED, obj1);
|
||||
|
||||
parent->spec_attr->children[index1] = obj2;
|
||||
obj2->parent = parent;
|
||||
|
||||
parent2->spec_attr->children[index2] = obj1;
|
||||
obj1->parent = parent2;
|
||||
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj2);
|
||||
lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj2);
|
||||
lv_obj_send_event(parent2, LV_EVENT_CHILD_CHANGED, obj1);
|
||||
lv_obj_send_event(parent2, LV_EVENT_CHILD_CREATED, obj1);
|
||||
|
||||
lv_obj_invalidate(parent);
|
||||
|
||||
if(parent != parent2) {
|
||||
lv_obj_invalidate(parent2);
|
||||
}
|
||||
lv_group_swap_obj(obj1, obj2);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * par = obj;
|
||||
const lv_obj_t * act_par;
|
||||
|
||||
do {
|
||||
act_par = par;
|
||||
par = lv_obj_get_parent(act_par);
|
||||
} while(par != NULL);
|
||||
|
||||
return (lv_obj_t *)act_par;
|
||||
}
|
||||
|
||||
lv_display_t * lv_obj_get_display(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * scr;
|
||||
|
||||
if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/
|
||||
else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/
|
||||
|
||||
lv_display_t * d;
|
||||
lv_ll_t * disp_head = disp_ll_p;
|
||||
LV_LL_READ(disp_head, d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
if(d->screens[i] == scr) return d;
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG_WARN("No screen found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return NULL;
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->parent;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t idx)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
uint32_t idu;
|
||||
if(idx < 0) {
|
||||
idx = obj->spec_attr->child_cnt + idx;
|
||||
if(idx < 0) return NULL;
|
||||
idu = (uint32_t) idx;
|
||||
}
|
||||
else {
|
||||
idu = idx;
|
||||
}
|
||||
|
||||
if(idu >= obj->spec_attr->child_cnt) return NULL;
|
||||
else return obj->spec_attr->children[idx];
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_child_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
int32_t i;
|
||||
int32_t cnt = (int32_t)obj->spec_attr->child_cnt;
|
||||
if(idx >= 0) {
|
||||
for(i = 0; i < cnt; i++) {
|
||||
if(obj->spec_attr->children[i]->class_p == class_p) {
|
||||
if(idx == 0) return obj->spec_attr->children[i];
|
||||
else idx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
idx++; /*-1 means the first child*/
|
||||
for(i = cnt - 1; i >= 0; i--) {
|
||||
if(obj->spec_attr->children[i]->class_p == class_p) {
|
||||
if(idx == 0) return obj->spec_attr->children[i];
|
||||
else idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_sibling(const lv_obj_t * obj, int32_t idx)
|
||||
{
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
int32_t sibling_idx = (int32_t)lv_obj_get_index(obj) + idx;
|
||||
if(sibling_idx < 0) return NULL;
|
||||
|
||||
return lv_obj_get_child(parent, sibling_idx);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_sibling_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
int32_t sibling_idx = (int32_t)lv_obj_get_index_by_type(obj, class_p) + idx;
|
||||
if(sibling_idx < 0) return NULL;
|
||||
|
||||
return lv_obj_get_child_by_type(parent, sibling_idx, class_p);
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_child_count(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->child_cnt;
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_child_count_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t cnt = 0;
|
||||
for(i = 0; i < obj->spec_attr->child_cnt; i++) {
|
||||
if(obj->spec_attr->children[i]->class_p == class_p) cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#if LV_USE_OBJ_NAME
|
||||
|
||||
void lv_obj_set_name(lv_obj_t * obj, const char * name)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(!obj->spec_attr->name_static && obj->spec_attr->name) lv_free((void *)obj->spec_attr->name);
|
||||
|
||||
if(name == NULL) {
|
||||
obj->spec_attr->name = NULL;
|
||||
obj->spec_attr->name_static = 1;
|
||||
}
|
||||
else {
|
||||
obj->spec_attr->name = lv_strdup(name);
|
||||
obj->spec_attr->name_static = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_set_name_static(lv_obj_t * obj, const char * name)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(!obj->spec_attr->name_static && obj->spec_attr->name) lv_free((void *)obj->spec_attr->name);
|
||||
|
||||
obj->spec_attr->name = name;
|
||||
obj->spec_attr->name_static = 1;
|
||||
}
|
||||
|
||||
const char * lv_obj_get_name(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
else return obj->spec_attr->name;
|
||||
}
|
||||
|
||||
void lv_obj_get_name_resolved(const lv_obj_t * obj, char buf[], size_t buf_size)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const char * name = lv_obj_get_name(obj);
|
||||
/*Use a default name which auto-indexing*/
|
||||
char name_buf[LV_OBJ_NAME_MAX_LEN];
|
||||
if(name == NULL) {
|
||||
lv_snprintf(name_buf, sizeof(name_buf), "%s_#", obj->class_p->name);
|
||||
name = name_buf;
|
||||
}
|
||||
|
||||
size_t name_len = lv_strlen(name);
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
|
||||
/*If the last character is # automatically index the children with the same name start*/
|
||||
if(parent && name_len > 0 && name[name_len - 1] == '#') {
|
||||
uint32_t child_cnt = lv_obj_get_child_count(parent);
|
||||
uint32_t cnt = 0;
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(parent, i);
|
||||
/*All siblings older siblings are checked, craft the name of this widget*/
|
||||
if(child == obj) {
|
||||
char num_buf[8];
|
||||
size_t num_len;
|
||||
num_len = lv_snprintf(num_buf, sizeof(num_buf), "%d", cnt);
|
||||
/*Is there enough space for the name and the index?*/
|
||||
if(buf_size > name_len + num_len) {
|
||||
/*E.g. buf = "some_name_", so trim the # from the end*/
|
||||
lv_strncpy(buf, name, name_len - 1);
|
||||
lv_strcpy(&buf[name_len - 1], num_buf);
|
||||
}
|
||||
else {
|
||||
/*Use the name as it is as a fallback*/
|
||||
lv_strlcpy(buf, obj->spec_attr->name, buf_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*Check the older siblings. IF they start with the same name count them*/
|
||||
else {
|
||||
const char * child_name = lv_obj_get_name(child);
|
||||
if(child_name == NULL) {
|
||||
/*If the name we are looking for start with the child's class name
|
||||
*increment the index. E.g. <class_name>_#*/
|
||||
size_t class_name_len = lv_strlen(child->class_p->name);
|
||||
if(name_len > 3 && class_name_len == name_len - 2 &&
|
||||
lv_strncmp(child->class_p->name, name, class_name_len) == 0) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
/*The name is set, check if it's e.g. <some_name>#*/
|
||||
else {
|
||||
if(lv_strcmp(child->spec_attr->name, name) == 0) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Just use the set name*/
|
||||
lv_strlcpy(buf, obj->spec_attr->name, buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_child_by_name(const lv_obj_t * parent, const char * path)
|
||||
{
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
|
||||
if(parent == NULL || parent->spec_attr == NULL || path == NULL) return NULL;
|
||||
|
||||
while(*path) {
|
||||
const char * segment = path;
|
||||
uint32_t len = 0;
|
||||
|
||||
/* Calculate the length of the current segment */
|
||||
while(path[len] && path[len] != '/')
|
||||
len++;
|
||||
|
||||
/* Look for a child whose resolved name exactly matches the segment */
|
||||
lv_obj_t * child = find_by_name_direct(parent, segment, len);
|
||||
if(!child) return NULL; /*Segment not found*/
|
||||
|
||||
/* Advance to the next segment */
|
||||
path += len;
|
||||
if(*path == '/') path++; /* Skip the '/' */
|
||||
|
||||
/* If there is no further segment, we've found the target child */
|
||||
if(*path == '\0') return child;
|
||||
|
||||
parent = child;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_find_by_name(const lv_obj_t * parent, const char * name)
|
||||
{
|
||||
if(parent == NULL) parent = lv_display_get_screen_active(NULL);
|
||||
if(parent == NULL) return NULL;
|
||||
|
||||
lv_obj_t * child = find_by_name_direct(parent, name, UINT16_MAX);
|
||||
if(child) return child;
|
||||
|
||||
/*Search children recursively*/
|
||||
uint32_t child_cnt = lv_obj_get_child_count(parent);
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
child = parent->spec_attr->children[i];
|
||||
lv_obj_t * found = lv_obj_find_by_name(child, name);
|
||||
if(found != NULL) return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OBJ_NAME*/
|
||||
|
||||
int32_t lv_obj_get_index(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent == NULL) return -1;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < parent->spec_attr->child_cnt; i++) {
|
||||
if(parent->spec_attr->children[i] == obj) return i;
|
||||
}
|
||||
|
||||
/*Shouldn't reach this point*/
|
||||
LV_ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t lv_obj_get_index_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent == NULL) return 0xFFFFFFFF;
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t idx = 0;
|
||||
for(i = 0; i < parent->spec_attr->child_cnt; i++) {
|
||||
lv_obj_t * child = parent->spec_attr->children[i];
|
||||
if(child->class_p == class_p) {
|
||||
if(child == obj) return idx;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/*Can happen if there was no children with the given type*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
walk_core(start_obj, cb, user_data);
|
||||
}
|
||||
|
||||
void lv_obj_dump_tree(lv_obj_t * start_obj)
|
||||
{
|
||||
if(start_obj == NULL) {
|
||||
lv_display_t * disp = lv_display_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
dump_tree_core(disp->screens[i], 0);
|
||||
}
|
||||
disp = lv_display_get_next(disp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dump_tree_core(start_obj, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_delete_async_cb(void * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_delete(obj);
|
||||
}
|
||||
|
||||
static void obj_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
|
||||
{
|
||||
/* If the input device is already in the release state,
|
||||
* there is no need to wait for the input device to be released
|
||||
*/
|
||||
if(lv_indev_get_state(indev) != LV_INDEV_STATE_RELEASED) {
|
||||
/*Wait for release to avoid accidentally triggering other obj to be clicked*/
|
||||
lv_indev_wait_release(indev);
|
||||
}
|
||||
|
||||
/*Reset the input device*/
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
|
||||
static void obj_delete_core(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->is_deleting)
|
||||
return;
|
||||
|
||||
obj->is_deleting = true;
|
||||
|
||||
/*Let the user free the resources used in `LV_EVENT_DELETE`*/
|
||||
lv_result_t res = lv_obj_send_event(obj, LV_EVENT_DELETE, NULL);
|
||||
if(res == LV_RESULT_INVALID) {
|
||||
obj->is_deleting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/*Clean registered event_cb*/
|
||||
if(obj->spec_attr) lv_event_remove_all(&(obj->spec_attr->event_list));
|
||||
|
||||
/*Recursively delete the children*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_delete_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
|
||||
/*Reset all input devices if the object to delete is used*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_POINTER || indev_type == LV_INDEV_TYPE_BUTTON) {
|
||||
if(indev->pointer.act_obj == obj || indev->pointer.scroll_obj == obj) {
|
||||
obj_indev_reset(indev, obj);
|
||||
}
|
||||
if(indev->pointer.last_pressed == obj) {
|
||||
indev->pointer.last_pressed = NULL;
|
||||
}
|
||||
if(indev->pointer.last_hovered == obj) {
|
||||
indev->pointer.last_hovered = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(indev->group == group && obj == lv_indev_get_active_obj()) {
|
||||
obj_indev_reset(indev, obj);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
/*Delete all pending async del-s*/
|
||||
lv_result_t async_cancel_res = LV_RESULT_OK;
|
||||
while(async_cancel_res == LV_RESULT_OK) {
|
||||
async_cancel_res = lv_async_call_cancel(lv_obj_delete_async_cb, obj);
|
||||
}
|
||||
|
||||
/*All children deleted. Now clean up the object specific data*/
|
||||
lv_obj_destruct(obj);
|
||||
|
||||
/*Remove the screen for the screen list*/
|
||||
if(obj->parent == NULL) {
|
||||
lv_display_t * disp = lv_obj_get_display(obj);
|
||||
uint32_t i;
|
||||
/*Find the screen in the list*/
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) break;
|
||||
}
|
||||
|
||||
uint32_t id = i;
|
||||
for(i = id; i < disp->screen_cnt - 1; i++) {
|
||||
disp->screens[i] = disp->screens[i + 1];
|
||||
}
|
||||
disp->screen_cnt--;
|
||||
disp->screens = lv_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
/*Remove the object from the child list of its parent*/
|
||||
else {
|
||||
int32_t id = lv_obj_get_index(obj);
|
||||
uint16_t i;
|
||||
for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) {
|
||||
obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1];
|
||||
}
|
||||
obj->parent->spec_attr->child_cnt--;
|
||||
obj->parent->spec_attr->children = lv_realloc(obj->parent->spec_attr->children,
|
||||
obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
|
||||
/*Free the object itself*/
|
||||
lv_free(obj);
|
||||
}
|
||||
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
lv_obj_tree_walk_res_t res = LV_OBJ_TREE_WALK_NEXT;
|
||||
|
||||
if(obj == NULL) {
|
||||
lv_display_t * disp = lv_display_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
walk_core(disp->screens[i], cb, user_data);
|
||||
}
|
||||
disp = lv_display_get_next(disp);
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_END; /*The value doesn't matter as it wasn't called recursively*/
|
||||
}
|
||||
|
||||
res = cb(obj, user_data);
|
||||
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
|
||||
if(res != LV_OBJ_TREE_WALK_SKIP_CHILDREN) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < lv_obj_get_child_count(obj); i++) {
|
||||
res = walk_core(lv_obj_get_child(obj, i), cb, user_data);
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
}
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_NEXT;
|
||||
}
|
||||
|
||||
static void dump_tree_core(lv_obj_t * obj, int32_t depth)
|
||||
{
|
||||
#if LV_USE_LOG
|
||||
const char * id;
|
||||
|
||||
#if LV_USE_OBJ_ID
|
||||
char buf[OBJ_DUMP_STRING_LEN];
|
||||
id = lv_obj_stringify_id(obj, buf, sizeof(buf));
|
||||
if(id == NULL) id = "obj0";
|
||||
#else
|
||||
id = "obj0";
|
||||
#endif
|
||||
|
||||
/*id of `obj0` is an invalid id for builtin id*/
|
||||
LV_LOG_USER("%*sobj:%p, id:%s;", (int)(2 * depth), "", (void *)obj, id);
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
if(obj && obj->spec_attr && obj->spec_attr->child_cnt) {
|
||||
for(uint32_t i = 0; i < obj->spec_attr->child_cnt; i++) {
|
||||
dump_tree_core(lv_obj_get_child(obj, i), depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static lv_obj_t * lv_obj_get_first_not_deleting_child(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
int32_t i;
|
||||
int32_t cnt = (int32_t)obj->spec_attr->child_cnt;
|
||||
for(i = 0; i < cnt; i++) {
|
||||
if(!obj->spec_attr->children[i]->is_deleting) {
|
||||
return obj->spec_attr->children[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_USE_OBJ_NAME
|
||||
|
||||
static lv_obj_t * find_by_name_direct(const lv_obj_t * parent, const char * name, size_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_count(parent);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = parent->spec_attr->children[i];
|
||||
|
||||
char child_name_resolved[LV_OBJ_NAME_MAX_LEN];
|
||||
lv_obj_get_name_resolved(child, child_name_resolved, sizeof(child_name_resolved));
|
||||
|
||||
if(len == UINT16_MAX) {
|
||||
if(lv_strcmp(child_name_resolved, name) == 0) return child;
|
||||
}
|
||||
else {
|
||||
if(lv_strncmp(child_name_resolved, name, len) == 0 &&
|
||||
child_name_resolved[len] == '\0') {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_OBJ_NAME*/
|
||||
321
inc/lvgl/src/core/lv_obj_tree.h
Normal file
321
inc/lvgl/src/core/lv_obj_tree.h
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* @file lv_obj_tree.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_TREE_H
|
||||
#define LV_OBJ_TREE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../display/lv_display.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_TREE_WALK_NEXT,
|
||||
LV_OBJ_TREE_WALK_SKIP_CHILDREN,
|
||||
LV_OBJ_TREE_WALK_END,
|
||||
} lv_obj_tree_walk_res_t;
|
||||
|
||||
typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(lv_obj_t *, void *);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Delete an object and all of its children.
|
||||
* Also remove the objects from their group and remove all animations (if any).
|
||||
* Send `LV_EVENT_DELETE` to deleted objects.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_delete(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Delete all children of an object.
|
||||
* Also remove the objects from their group and remove all animations (if any).
|
||||
* Send `LV_EVENT_DELETE` to deleted objects.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_clean(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Delete an object after some delay
|
||||
* @param obj pointer to an object
|
||||
* @param delay_ms time to wait before delete in milliseconds
|
||||
*/
|
||||
void lv_obj_delete_delayed(lv_obj_t * obj, uint32_t delay_ms);
|
||||
|
||||
/**
|
||||
* A function to be easily used in animation ready callback to delete an object when the animation is ready
|
||||
* @param a pointer to the animation
|
||||
*/
|
||||
void lv_obj_delete_anim_completed_cb(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Helper function for asynchronously deleting objects.
|
||||
* Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent).
|
||||
* @param obj object to delete
|
||||
* @see lv_async_call
|
||||
*/
|
||||
void lv_obj_delete_async(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Move the parent of an object. The relative coordinates will be kept.
|
||||
*
|
||||
* @param obj pointer to an object whose parent needs to be changed
|
||||
* @param parent pointer to the new parent
|
||||
*/
|
||||
void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);
|
||||
|
||||
/**
|
||||
* Swap the positions of two objects.
|
||||
* When used in listboxes, it can be used to sort the listbox items.
|
||||
* @param obj1 pointer to the first object
|
||||
* @param obj2 pointer to the second object
|
||||
*/
|
||||
void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2);
|
||||
|
||||
/**
|
||||
* moves the object to the given index in its parent.
|
||||
* When used in listboxes, it can be used to sort the listbox items.
|
||||
* @param obj pointer to the object to be moved.
|
||||
* @param index new index in parent. -1 to count from the back
|
||||
* @note to move to the background: lv_obj_move_to_index(obj, 0)
|
||||
* @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1)
|
||||
*/
|
||||
void lv_obj_move_to_index(lv_obj_t * obj, int32_t index);
|
||||
|
||||
/**
|
||||
* Get the screen of an object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the object's screen
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the display of the object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the object's display
|
||||
*/
|
||||
lv_display_t * lv_obj_get_display(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the parent of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the parent of the object. (NULL if `obj` was a screen)
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the child of an object by the child's index.
|
||||
* @param obj pointer to an object whose child should be get
|
||||
* @param idx the index of the child.
|
||||
* 0: the oldest (firstly created) child
|
||||
* 1: the second oldest
|
||||
* child count-1: the youngest
|
||||
* -1: the youngest
|
||||
* -2: the second youngest
|
||||
* @return pointer to the child or NULL if the index was invalid
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t idx);
|
||||
|
||||
/**
|
||||
* Get the child of an object by the child's index. Consider the children only with a given type.
|
||||
* @param obj pointer to an object whose child should be get
|
||||
* @param idx the index of the child.
|
||||
* 0: the oldest (firstly created) child
|
||||
* 1: the second oldest
|
||||
* child count-1: the youngest
|
||||
* -1: the youngest
|
||||
* -2: the second youngest
|
||||
* @param class_p the type of the children to check
|
||||
* @return pointer to the child or NULL if the index was invalid
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child_by_type(const lv_obj_t * obj, int32_t idx,
|
||||
const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Return a sibling of an object
|
||||
* @param obj pointer to an object whose sibling should be get
|
||||
* @param idx 0: `obj` itself
|
||||
* -1: the first older sibling
|
||||
* -2: the next older sibling
|
||||
* 1: the first younger sibling
|
||||
* 2: the next younger sibling
|
||||
* etc
|
||||
* @return pointer to the requested sibling or NULL if there is no such sibling
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_sibling(const lv_obj_t * obj, int32_t idx);
|
||||
|
||||
/**
|
||||
* Return a sibling of an object. Consider the siblings only with a given type.
|
||||
* @param obj pointer to an object whose sibling should be get
|
||||
* @param idx 0: `obj` itself
|
||||
* -1: the first older sibling
|
||||
* -2: the next older sibling
|
||||
* 1: the first younger sibling
|
||||
* 2: the next younger sibling
|
||||
* etc
|
||||
* @param class_p the type of the children to check
|
||||
* @return pointer to the requested sibling or NULL if there is no such sibling
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_sibling_by_type(const lv_obj_t * obj, int32_t idx,
|
||||
const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Get the number of children
|
||||
* @param obj pointer to an object
|
||||
* @return the number of children
|
||||
*/
|
||||
uint32_t lv_obj_get_child_count(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the number of children having a given type.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p the type of the children to check
|
||||
* @return the number of children
|
||||
*/
|
||||
|
||||
uint32_t lv_obj_get_child_count_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
#if LV_USE_OBJ_NAME
|
||||
|
||||
/**
|
||||
* Set a name for a widget. The name will be allocated and freed when the
|
||||
* widget is deleted or a new name is set.
|
||||
* @param obj pointer to an object
|
||||
* @param name the name to set. If set to `NULL` the default "<widget_type>_#"
|
||||
* name will be used.
|
||||
* @note If the name ends with a `#`, older siblings with the same name
|
||||
* will be counted, and the `#` will be replaced by the index of the
|
||||
* given widget. For example, creating multiple widgets with the name
|
||||
* "mybtn_#" will result in resolved names like "mybtn_0", "mybtn_1",
|
||||
* "mybtn_2", etc. The name is resolved when `lv_obj_get_name_resolved`
|
||||
* is called, so the result reflects the currently existing widgets at
|
||||
* that time.
|
||||
*/
|
||||
void lv_obj_set_name(lv_obj_t * obj, const char * name);
|
||||
|
||||
/**
|
||||
* Set a name for a widget. Only a pointer will be saved.
|
||||
* @param obj pointer to an object
|
||||
* @param name the name to set. If set to `NULL` the default "<widget_type>_#"
|
||||
* name will be used.
|
||||
* @note If the name ends with a `#`, older siblings with the same name
|
||||
* will be counted, and the `#` will be replaced by the index of the
|
||||
* given widget. For example, creating multiple widgets with the name
|
||||
* "mybtn_#" will result in resolved names like "mybtn_0", "mybtn_1",
|
||||
* "mybtn_2", etc. The name is resolved when `lv_obj_get_name_resolved`
|
||||
* is called, so the result reflects the currently existing widgets at
|
||||
* that time.
|
||||
*/
|
||||
void lv_obj_set_name_static(lv_obj_t * obj, const char * name);
|
||||
|
||||
/**
|
||||
* Get the set name as it was set.
|
||||
* @param obj pointer to an object
|
||||
* @return get the set name or NULL if it wasn't set yet
|
||||
*/
|
||||
const char * lv_obj_get_name(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the set name or craft a name automatically.
|
||||
* @param obj pointer to an object
|
||||
* @param buf buffer to store the name
|
||||
* @param buf_size the size of the buffer in bytes
|
||||
* @note If the name ends with a `#`, older siblings with the same name
|
||||
* will be counted, and the `#` will be replaced by the index of the
|
||||
* given widget. For example, creating multiple widgets with the name
|
||||
* "mybtn_#" will result in resolved names like "mybtn_0", "mybtn_1",
|
||||
* "mybtn_2", etc. The name is resolved when `lv_obj_get_name_resolved`
|
||||
* is called, so the result reflects the currently existing widgets at
|
||||
* that time.
|
||||
*/
|
||||
void lv_obj_get_name_resolved(const lv_obj_t * obj, char buf[], size_t buf_size);
|
||||
|
||||
/**
|
||||
* Find a child with a given name on a parent. This child doesn't have to be the
|
||||
* direct child of the parent. First direct children of the parent will be checked,
|
||||
* and the direct children of the first child, etc. (Breadth-first search).
|
||||
*
|
||||
* If the name of a widget was not set a name like "lv_button_1" will
|
||||
* be created for it using `lv_obj_get_name_resolved`.
|
||||
*
|
||||
* @param parent the widget where the search should start
|
||||
* @return the found widget or NULL if not found.
|
||||
*/
|
||||
lv_obj_t * lv_obj_find_by_name(const lv_obj_t * parent, const char * name);
|
||||
|
||||
/**
|
||||
* Get an object by name. The name can be a path too, for example
|
||||
* "main_container/lv_button_1/label".
|
||||
* In this case the first part of the name-path should be the direct child of the parent,
|
||||
* the second part, should the direct child of first one, etc.
|
||||
*
|
||||
* If the name of a widget was not set a name like "lv_button_1" will
|
||||
* be created for it using `lv_obj_get_name_resolved`.
|
||||
*
|
||||
* @param parent the widget where the search should start
|
||||
* @return the found widget or NULL if not found.
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child_by_name(const lv_obj_t * parent, const char * name_path);
|
||||
|
||||
#endif /*LV_USE_OBJ_NAME*/
|
||||
|
||||
/**
|
||||
* Get the index of a child.
|
||||
* @param obj pointer to an object
|
||||
* @return the child index of the object.
|
||||
* E.g. 0: the oldest (firstly created child).
|
||||
* (-1 if child could not be found or no parent exists)
|
||||
*/
|
||||
int32_t lv_obj_get_index(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the index of a child. Consider the children only with a given type.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p the type of the children to check
|
||||
* @return the child index of the object.
|
||||
* E.g. 0: the oldest (firstly created child with the given class).
|
||||
* (-1 if child could not be found or no parent exists)
|
||||
*/
|
||||
int32_t lv_obj_get_index_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Iterate through all children of any object.
|
||||
* @param start_obj start integrating from this object
|
||||
* @param cb call this callback on the objects
|
||||
* @param user_data pointer to any user related data (will be passed to `cb`)
|
||||
*/
|
||||
void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Iterate through all children of any object and print their ID.
|
||||
* @param start_obj start integrating from this object
|
||||
*/
|
||||
void lv_obj_dump_tree(lv_obj_t * start_obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_TREE_H*/
|
||||
1098
inc/lvgl/src/core/lv_observer.c
Normal file
1098
inc/lvgl/src/core/lv_observer.c
Normal file
File diff suppressed because it is too large
Load Diff
622
inc/lvgl/src/core/lv_observer.h
Normal file
622
inc/lvgl/src/core/lv_observer.h
Normal file
@@ -0,0 +1,622 @@
|
||||
/**
|
||||
* @file lv_observer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBSERVER_H
|
||||
#define LV_OBSERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../misc/lv_ext_data.h"
|
||||
#include "lv_obj.h"
|
||||
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Values for lv_subject_t's `type` field
|
||||
*/
|
||||
typedef enum {
|
||||
LV_SUBJECT_TYPE_INVALID = 0, /**< indicates Subject not initialized yet */
|
||||
LV_SUBJECT_TYPE_NONE = 1, /**< a null value like None or NILt */
|
||||
LV_SUBJECT_TYPE_INT = 2, /**< an int32_t */
|
||||
LV_SUBJECT_TYPE_FLOAT = 3, /**< a float, requires `LV_USE_FLOAT 1` */
|
||||
LV_SUBJECT_TYPE_POINTER = 4, /**< a void pointer */
|
||||
LV_SUBJECT_TYPE_COLOR = 5, /**< an lv_color_t */
|
||||
LV_SUBJECT_TYPE_GROUP = 6, /**< an array of Subjects */
|
||||
LV_SUBJECT_TYPE_STRING = 7, /**< a char pointer */
|
||||
} lv_subject_type_t;
|
||||
|
||||
/**
|
||||
* A common type to handle all the various observable types in the same way
|
||||
*/
|
||||
typedef union {
|
||||
int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers) */
|
||||
const void * pointer; /**< Constant pointer (string buffer, format string, font, cone text, etc.) */
|
||||
lv_color_t color; /**< Color */
|
||||
#if LV_USE_FLOAT
|
||||
float float_v; /**< Floating point value*/
|
||||
#endif
|
||||
} lv_subject_value_t;
|
||||
|
||||
/**
|
||||
* The Subject (an observable value)
|
||||
*/
|
||||
struct _lv_subject_t {
|
||||
#if LV_USE_EXT_DATA
|
||||
lv_ext_data_t ext_data;
|
||||
#endif
|
||||
lv_ll_t subs_ll; /**< Subscribers */
|
||||
lv_subject_value_t value; /**< Current value */
|
||||
lv_subject_value_t prev_value; /**< Previous value */
|
||||
lv_subject_value_t min_value; /**< Minimum value for min. int or float*/
|
||||
lv_subject_value_t max_value; /**< Maximum value for max. int or float*/
|
||||
void * user_data; /**< Additional parameter, can be used freely by user */
|
||||
uint32_t type : 4; /**< One of the LV_SUBJECT_TYPE_... values */
|
||||
uint32_t size : 24; /**< String buffer size or group length */
|
||||
uint32_t notify_restart_query : 1; /**< If an Observer was deleted during notification,
|
||||
* start notifying from the beginning. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback called to notify Observer that Subject's value has changed
|
||||
* @param observer pointer to Observer
|
||||
* @param subject pointer to Subject being observed
|
||||
*/
|
||||
typedef void (*lv_observer_cb_t)(lv_observer_t * observer, lv_subject_t * subject);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
/**
|
||||
* @brief Attaches external user data to an integer Subject with lifecycle management
|
||||
*
|
||||
* Associates arbitrary user-defined data with an LVGL observer and registers a destructor
|
||||
* callback that will be automatically invoked when the observer is deleted. This enables:
|
||||
* - Safe resource cleanup through the destructor mechanism
|
||||
* - Contextual data storage for observer callbacks
|
||||
* - Proper memory management for observer-related resources
|
||||
*
|
||||
* @param subject pointer to Subject
|
||||
* @param data User-defined data pointer to associate
|
||||
* @param free_cb Cleanup function called when:
|
||||
* - Observer is explicitly deleted
|
||||
* - Observed object is deleted
|
||||
* - New data replaces current association
|
||||
* NULL indicates no cleanup required
|
||||
*/
|
||||
void lv_subject_set_external_data(lv_subject_t * subject, void * data, void (* free_cb)(void * data));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize an integer-type Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @param value initial value
|
||||
*/
|
||||
void lv_subject_init_int(lv_subject_t * subject, int32_t value);
|
||||
|
||||
/**
|
||||
* Set value of an integer Subject and notify Observers.
|
||||
* @param subject pointer to Subject
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_subject_set_int(lv_subject_t * subject, int32_t value);
|
||||
|
||||
/**
|
||||
* Get current value of an integer Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
int32_t lv_subject_get_int(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get previous value of an integer Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
int32_t lv_subject_get_previous_int(lv_subject_t * subject);
|
||||
|
||||
|
||||
/**
|
||||
* Set a minimum value for an integer subject
|
||||
* @param subject pointer to Subject
|
||||
* @param min_value the minimum value
|
||||
*/
|
||||
void lv_subject_set_min_value_int(lv_subject_t * subject, int32_t min_value);
|
||||
|
||||
/**
|
||||
* Set a maximum value for an integer subject
|
||||
* @param subject pointer to Subject
|
||||
* @param max_value the maximum value
|
||||
*/
|
||||
void lv_subject_set_max_value_int(lv_subject_t * subject, int32_t max_value);
|
||||
|
||||
#if LV_USE_FLOAT
|
||||
|
||||
/**
|
||||
* Initialize an float-type Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @param value initial value
|
||||
*/
|
||||
void lv_subject_init_float(lv_subject_t * subject, float value);
|
||||
|
||||
/**
|
||||
* Set value of an float Subject and notify Observers.
|
||||
* @param subject pointer to Subject
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_subject_set_float(lv_subject_t * subject, float value);
|
||||
|
||||
/**
|
||||
* Get current value of an float Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
float lv_subject_get_float(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get previous value of an float Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
float lv_subject_get_previous_float(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Set a minimum value for a float subject
|
||||
* @param subject pointer to Subject
|
||||
* @param min_value the minimum value
|
||||
*/
|
||||
void lv_subject_set_min_value_float(lv_subject_t * subject, float min_value);
|
||||
|
||||
/**
|
||||
* Set a maximum value for a float subject
|
||||
* @param subject pointer to Subject
|
||||
* @param max_value the maximum value
|
||||
*/
|
||||
void lv_subject_set_max_value_float(lv_subject_t * subject, float max_value);
|
||||
|
||||
#endif /*LV_USE_FLOAT*/
|
||||
|
||||
/**
|
||||
* Initialize a string-type Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @param buf pointer to buffer to store string
|
||||
* @param prev_buf pointer to buffer to store previous string; can be NULL if not used
|
||||
* @param size size of buffer(s)
|
||||
* @param value initial value of string, e.g. "hello"
|
||||
* @note A string Subject stores its own copy of the string, not just the pointer.
|
||||
*/
|
||||
void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value);
|
||||
|
||||
/**
|
||||
* Copy a string to a Subject and notify Observers if it changed.
|
||||
* @param subject pointer to Subject
|
||||
* @param buf new string
|
||||
*/
|
||||
void lv_subject_copy_string(lv_subject_t * subject, const char * buf);
|
||||
|
||||
/**
|
||||
* Format a new string, updating Subject, and notify Observers if it changed.
|
||||
* @param subject pointer to Subject
|
||||
* @param format format string
|
||||
*/
|
||||
void lv_subject_snprintf(lv_subject_t * subject, const char * format, ...) LV_FORMAT_ATTRIBUTE(2, 3);
|
||||
|
||||
/**
|
||||
* Get current value of a string Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return pointer to buffer containing current value
|
||||
*/
|
||||
const char * lv_subject_get_string(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get previous value of a string Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return pointer to buffer containing previous value
|
||||
* @note NULL will be returned if NULL was passed in `lv_subject_init_string()`
|
||||
* as `prev_buf`.
|
||||
*/
|
||||
const char * lv_subject_get_previous_string(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize a pointer-type Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @param value initial value
|
||||
*/
|
||||
void lv_subject_init_pointer(lv_subject_t * subject, void * value);
|
||||
|
||||
/**
|
||||
* Set value of a pointer Subject and notify Observers (regardless of whether it changed).
|
||||
* @param subject pointer to Subject
|
||||
* @param ptr new value
|
||||
*/
|
||||
void lv_subject_set_pointer(lv_subject_t * subject, void * ptr);
|
||||
|
||||
/**
|
||||
* Get current value of a pointer Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
const void * lv_subject_get_pointer(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get previous value of a pointer Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return previous value
|
||||
*/
|
||||
const void * lv_subject_get_previous_pointer(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize a color-type Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @param color initial value
|
||||
*/
|
||||
void lv_subject_init_color(lv_subject_t * subject, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set value of a color Subject and notify Observers if it changed.
|
||||
* @param subject pointer to Subject
|
||||
* @param color new value
|
||||
*/
|
||||
void lv_subject_set_color(lv_subject_t * subject, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Get current value of a color Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return current value
|
||||
*/
|
||||
lv_color_t lv_subject_get_color(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get previous value of a color Subject.
|
||||
* @param subject pointer to Subject
|
||||
* @return previous value
|
||||
*/
|
||||
lv_color_t lv_subject_get_previous_color(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize a Group-type Subject.
|
||||
* @param group_subject pointer to Group-type Subject
|
||||
* @param list list of other Subject addresses; when any of these have values
|
||||
updated, Observers of `group_subject` will be notified.
|
||||
* @param list_len number of elements in `list[]`
|
||||
*/
|
||||
void lv_subject_init_group(lv_subject_t * group_subject, lv_subject_t * list[], uint32_t list_len);
|
||||
|
||||
/**
|
||||
* Remove all Observers from a Subject and free allocated memory, and delete
|
||||
* any associated Widget-Binding events. This leaves `subject` "disconnected" from
|
||||
* all Observers and all associated Widget events established through Widget Binding.
|
||||
* @param subject pointer to Subject
|
||||
* @note This can safely be called regardless of whether any Observers
|
||||
* added with `lv_subject_add_observer_obj()` or bound to a Widget Property
|
||||
* with one of the `..._bind_...()` functions.
|
||||
*/
|
||||
void lv_subject_deinit(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get an element from Subject Group's list.
|
||||
* @param subject pointer to Group-type Subject
|
||||
* @param index index of element to get
|
||||
* @return pointer to indexed Subject from list, or NULL if index is out of bounds
|
||||
*/
|
||||
lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index);
|
||||
|
||||
/**
|
||||
* Add Observer to Subject. When Subject's value changes `observer_cb` will be called.
|
||||
* @param subject pointer to Subject
|
||||
* @param observer_cb notification callback
|
||||
* @param user_data optional user data
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t observer_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Add Observer to Subject for a Widget.
|
||||
* When the Widget is deleted, Observer will be unsubscribed from Subject automatically.
|
||||
* @param subject pointer to Subject
|
||||
* @param observer_cb notification callback
|
||||
* @param obj pointer to Widget
|
||||
* @param user_data optional user data
|
||||
* @return pointer to newly-created Observer
|
||||
* @note Do not call `lv_observer_remove()` on Observers created this way.
|
||||
* Only clean up such Observers by either:
|
||||
* - deleting the Widget, or
|
||||
* - calling `lv_subject_deinit()` to gracefully de-couple and
|
||||
* remove all Observers.
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t observer_cb, lv_obj_t * obj,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Add an Observer to a Subject and also save a target pointer.
|
||||
* @param subject pointer to Subject
|
||||
* @param observer_cb notification callback
|
||||
* @param target any pointer (NULL is okay)
|
||||
* @param user_data optional user data
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t observer_cb,
|
||||
void * target, void * user_data);
|
||||
|
||||
/**
|
||||
* Remove Observer from its Subject.
|
||||
* @param observer pointer to Observer
|
||||
*/
|
||||
void lv_observer_remove(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Remove Observers associated with Widget `obj` from specified `subject` or all Subjects.
|
||||
* @param obj pointer to Widget whose Observers should be removed
|
||||
* @param subject Subject to remove Widget from, or NULL to remove from all Subjects
|
||||
* @note This function can be used e.g. when a Widget's Subject(s) needs to
|
||||
* be replaced by other Subject(s)
|
||||
*/
|
||||
void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get target of an Observer.
|
||||
* @param observer pointer to Observer
|
||||
* @return pointer to saved target
|
||||
*/
|
||||
void * lv_observer_get_target(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Get target Widget of Observer.
|
||||
* This is the same as `lv_observer_get_target()`, except it returns `target`
|
||||
* as an `lv_obj_t *`.
|
||||
* @param observer pointer to Observer
|
||||
* @return pointer to saved Widget target
|
||||
*/
|
||||
lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Get Observer's user data.
|
||||
* @param observer pointer to Observer
|
||||
* @return void pointer to saved user data
|
||||
*/
|
||||
void * lv_observer_get_user_data(const lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Notify all Observers of Subject.
|
||||
* @param subject pointer to Subject
|
||||
*/
|
||||
void lv_subject_notify(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Add an event handler to increment (or decrement) the value of a subject on a trigger.
|
||||
* @param obj pointer to a widget
|
||||
* @param subject pointer to a subject to change
|
||||
* @param trigger the trigger on which the subject should be changed
|
||||
* @param step value to add on trigger
|
||||
* if the minimum value is reached, the maximum value will be set on rollover.
|
||||
*/
|
||||
lv_subject_increment_dsc_t * lv_obj_add_subject_increment_event(lv_obj_t * obj, lv_subject_t * subject,
|
||||
lv_event_code_t trigger, int32_t step);
|
||||
|
||||
/**
|
||||
* Set the minimum subject value to set by the event
|
||||
* @param obj pointer to the Widget to which the event is attached
|
||||
* @param dsc pointer to the descriptor returned by `lv_obj_add_subject_increment_event()`
|
||||
* @param min_value the minimum value to set
|
||||
*/
|
||||
void lv_obj_set_subject_increment_event_min_value(lv_obj_t * obj, lv_subject_increment_dsc_t * dsc, int32_t min_value);
|
||||
|
||||
/**
|
||||
* Set the maximum subject value to set by the event
|
||||
* @param obj pointer to the Widget to which the event is attached
|
||||
* @param dsc pointer to the descriptor returned by `lv_obj_add_subject_increment_event()`
|
||||
* @param max_value the maximum value to set
|
||||
*/
|
||||
void lv_obj_set_subject_increment_event_max_value(lv_obj_t * obj, lv_subject_increment_dsc_t * dsc, int32_t max_value);
|
||||
|
||||
/**
|
||||
* Set what to do when the min/max value is crossed.
|
||||
* @param obj pointer to the Widget to which the event is attached
|
||||
* @param dsc pointer to the descriptor returned by `lv_obj_add_subject_increment_event()`
|
||||
* @param rollover false: stop at the min/max value; true: jump to the other end
|
||||
* @note the subject also can have min/max values and always the smaller range will be considered
|
||||
*/
|
||||
void lv_obj_set_subject_increment_event_rollover(lv_obj_t * obj, lv_subject_increment_dsc_t * dsc, bool rollover);
|
||||
|
||||
/**
|
||||
* Toggle the value of an integer subject on an event. If it was != 0 it will be 0.
|
||||
* If it was 0, it will be 1.
|
||||
* @param obj pointer to a widget
|
||||
* @param subject pointer to a subject to toggle
|
||||
* @param trigger the trigger on which the subject should be changed
|
||||
*/
|
||||
void lv_obj_add_subject_toggle_event(lv_obj_t * obj, lv_subject_t * subject, lv_event_code_t trigger);
|
||||
|
||||
/**
|
||||
* Set the value of an integer subject.
|
||||
* @param obj pointer to a widget
|
||||
* @param subject pointer to a subject to change
|
||||
* @param trigger the trigger on which the subject should be changed
|
||||
* @param value the value to set
|
||||
*/
|
||||
void lv_obj_add_subject_set_int_event(lv_obj_t * obj, lv_subject_t * subject, lv_event_code_t trigger, int32_t value);
|
||||
|
||||
|
||||
#if LV_USE_FLOAT
|
||||
/**
|
||||
* Set the value of a float subject.
|
||||
* @param obj pointer to a widget
|
||||
* @param subject pointer to a subject to change
|
||||
* @param trigger the trigger on which the subject should be changed
|
||||
* @param value the value to set
|
||||
*/
|
||||
void lv_obj_add_subject_set_float_event(lv_obj_t * obj, lv_subject_t * subject, lv_event_code_t trigger, float value);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the value of a string subject.
|
||||
* @param obj pointer to a widget
|
||||
* @param subject pointer to a subject to change
|
||||
* @param trigger the trigger on which the subject should be changed
|
||||
* @param value the value to set
|
||||
*/
|
||||
void lv_obj_add_subject_set_string_event(lv_obj_t * obj, lv_subject_t * subject, lv_event_code_t trigger,
|
||||
const char * value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is not equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag,
|
||||
int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is greater than a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_gt(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is greater than or equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_ge(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is less than a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_lt(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's flag(s) if an integer Subject's value is less than or equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param flag flag(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_le(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
|
||||
/**
|
||||
* Set Widget's state(s) if an integer Subject's value is equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set a Widget's state(s) if an integer Subject's value is not equal to a reference value, clear flag otherwise
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state,
|
||||
int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's state(s) if an integer Subject's value is greater than a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_gt(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's state(s) if an integer Subject's value is greater than or equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_ge(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's state(s) if an integer Subject's value is less than a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_lt(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set Widget's state(s) if an integer Subject's value is less than or equal to a reference value, clear flag otherwise.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to Subject
|
||||
* @param state state(s) (can be bit-wise OR-ed) to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare Subject's value with
|
||||
* @return pointer to newly-created Observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_le(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set an integer Subject to 1 when a Widget is checked and set it 0 when unchecked, and
|
||||
* clear Widget's checked state when Subject's value changes to 0 and set it when non-zero.
|
||||
* @param obj pointer to Widget
|
||||
* @param subject pointer to a Subject
|
||||
* @return pointer to newly-created Observer
|
||||
* @note Ensure Widget's `LV_OBJ_FLAG_CHECKABLE` flag is set.
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OBSERVER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBSERVER_H*/
|
||||
67
inc/lvgl/src/core/lv_observer_private.h
Normal file
67
inc/lvgl/src/core/lv_observer_private.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file lv_observer_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBSERVER_PRIVATE_H
|
||||
#define LV_OBSERVER_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_observer.h"
|
||||
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* The observer object: a descriptor returned when subscribing LVGL widgets to subjects
|
||||
*/
|
||||
struct _lv_observer_t {
|
||||
lv_subject_t * subject; /**< Observed subject */
|
||||
lv_observer_cb_t cb; /**< Callback that notifies when value changes */
|
||||
void * target; /**< A target for the observer, e.g. a widget or any pointer */
|
||||
void * user_data; /**< Additional parameter supplied when subscribing */
|
||||
uint32_t auto_free_user_data : 1; /**< Automatically free user data when observer is removed */
|
||||
uint32_t notified : 1; /**< Was observer already notified? */
|
||||
uint32_t for_obj : 1; /**< Is `target` a pointer to a Widget (`lv_obj_t *`)? */
|
||||
};
|
||||
|
||||
/**
|
||||
* Descriptor created by `lv_obj_add_subject_increment_event()`
|
||||
*/
|
||||
struct _lv_subject_increment_dsc_t {
|
||||
lv_subject_t * subject; /**< The subject to adjust*/
|
||||
int32_t step; /**< The step add to the subject */
|
||||
bool rollover; /**< Where to start over from the other end when one end is exceeded*/
|
||||
int32_t min_value; /**< Don't set a value smaller than this */
|
||||
int32_t max_value; /**< Don't set a value larger than this */
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OBSERVER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBSERVER_PRIVATE_H*/
|
||||
1466
inc/lvgl/src/core/lv_refr.c
Normal file
1466
inc/lvgl/src/core/lv_refr.c
Normal file
File diff suppressed because it is too large
Load Diff
74
inc/lvgl/src/core/lv_refr.h
Normal file
74
inc/lvgl/src/core/lv_refr.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @file lv_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_REFR_H
|
||||
#define LV_REFR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../display/lv_display.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Redraw the invalidated areas now.
|
||||
* Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process
|
||||
* can prevent the call of `lv_timer_handler`. In this case if the GUI is updated in the process
|
||||
* (e.g. progress bar) this function can be called when the screen should be updated.
|
||||
* @param disp pointer to display to refresh. NULL to refresh all displays.
|
||||
*/
|
||||
void lv_refr_now(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Redrawn on object and all its children using the passed draw context
|
||||
* @param layer pointer to a layer where to draw.
|
||||
* @param obj the start object from the redraw should start
|
||||
*/
|
||||
void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Called periodically to handle the refreshing
|
||||
* @param timer pointer to the timer itself, or `NULL`
|
||||
*/
|
||||
void lv_display_refr_timer(lv_timer_t * timer);
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_REFR_H*/
|
||||
85
inc/lvgl/src/core/lv_refr_private.h
Normal file
85
inc/lvgl/src/core/lv_refr_private.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @file lv_refr_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_REFR_PRIVATE_H
|
||||
#define LV_REFR_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void lv_refr_init(void);
|
||||
|
||||
/**
|
||||
* Deinitialize the screen refresh subsystem
|
||||
*/
|
||||
void lv_refr_deinit(void);
|
||||
|
||||
/**
|
||||
* Invalidate an area on display to redraw it
|
||||
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
|
||||
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is
|
||||
* only one display)
|
||||
* @return LV_RESULT_OK: the area is invalidated; LV_RESULT_INVALID: the area wasn't invalidated.
|
||||
*/
|
||||
lv_result_t lv_inv_area(lv_display_t * disp, const lv_area_t * area_p);
|
||||
|
||||
/**
|
||||
* Get the display which is being refreshed
|
||||
* @return the display being refreshed
|
||||
*/
|
||||
lv_display_t * lv_refr_get_disp_refreshing(void);
|
||||
|
||||
/**
|
||||
* Set the display which is being refreshed
|
||||
* @param disp the display being refreshed
|
||||
*/
|
||||
void lv_refr_set_disp_refreshing(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Search the most top object which fully covers an area
|
||||
* @param area_p pointer to an area
|
||||
* @param obj the first object to start the searching (typically a screen)
|
||||
* @return
|
||||
*/
|
||||
lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Render an object to a layer
|
||||
* @param layer target drawing layer
|
||||
* @param obj object to render
|
||||
*/
|
||||
void lv_obj_refr(lv_layer_t * layer, lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_REFR_PRIVATE_H*/
|
||||
178
inc/lvgl/src/debugging/monkey/lv_monkey.c
Normal file
178
inc/lvgl/src/debugging/monkey/lv_monkey.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file lv_monkey.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_monkey_private.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include "../../display/lv_display.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MONKEY_PERIOD_RANGE_MIN_DEF 100
|
||||
#define MONKEY_PERIOD_RANGE_MAX_DEF 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_monkey_t {
|
||||
lv_monkey_config_t config;
|
||||
lv_indev_data_t indev_data;
|
||||
lv_indev_t * indev;
|
||||
lv_timer_t * timer;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
static const lv_key_t lv_key_map[] = {
|
||||
LV_KEY_UP,
|
||||
LV_KEY_DOWN,
|
||||
LV_KEY_RIGHT,
|
||||
LV_KEY_LEFT,
|
||||
LV_KEY_ESC,
|
||||
LV_KEY_DEL,
|
||||
LV_KEY_BACKSPACE,
|
||||
LV_KEY_ENTER,
|
||||
LV_KEY_NEXT,
|
||||
LV_KEY_PREV,
|
||||
LV_KEY_HOME,
|
||||
LV_KEY_END,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static int32_t lv_monkey_random(int32_t howsmall, int32_t howbig);
|
||||
static void lv_monkey_timer_cb(lv_timer_t * timer);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_monkey_config_init(lv_monkey_config_t * config)
|
||||
{
|
||||
lv_memzero(config, sizeof(lv_monkey_config_t));
|
||||
config->type = LV_INDEV_TYPE_POINTER;
|
||||
config->period_range.min = MONKEY_PERIOD_RANGE_MIN_DEF;
|
||||
config->period_range.max = MONKEY_PERIOD_RANGE_MAX_DEF;
|
||||
}
|
||||
|
||||
lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_malloc_zeroed(sizeof(lv_monkey_t));
|
||||
LV_ASSERT_MALLOC(monkey);
|
||||
|
||||
monkey->config = *config;
|
||||
monkey->timer = lv_timer_create(lv_monkey_timer_cb, monkey->config.period_range.min, monkey);
|
||||
lv_timer_pause(monkey->timer);
|
||||
|
||||
monkey->indev = lv_indev_create();
|
||||
lv_indev_set_type(monkey->indev, config->type);
|
||||
lv_indev_set_read_cb(monkey->indev, lv_monkey_read_cb);
|
||||
lv_indev_set_user_data(monkey->indev, monkey);
|
||||
return monkey;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_monkey_get_indev(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return monkey->indev;
|
||||
}
|
||||
|
||||
void lv_monkey_set_enable(lv_monkey_t * monkey, bool en)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
en ? lv_timer_resume(monkey->timer) : lv_timer_pause(monkey->timer);
|
||||
}
|
||||
|
||||
bool lv_monkey_get_enable(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return !lv_timer_get_paused(monkey->timer);
|
||||
}
|
||||
|
||||
void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
monkey->user_data = user_data;
|
||||
}
|
||||
|
||||
void * lv_monkey_get_user_data(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return monkey->user_data;
|
||||
}
|
||||
|
||||
void lv_monkey_delete(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
|
||||
lv_timer_delete(monkey->timer);
|
||||
lv_indev_delete(monkey->indev);
|
||||
lv_free(monkey);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_indev_get_user_data(indev);
|
||||
|
||||
data->btn_id = monkey->indev_data.btn_id;
|
||||
data->point = monkey->indev_data.point;
|
||||
data->enc_diff = monkey->indev_data.enc_diff;
|
||||
data->state = monkey->indev_data.state;
|
||||
}
|
||||
|
||||
static int32_t lv_monkey_random(int32_t howsmall, int32_t howbig)
|
||||
{
|
||||
if(howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
int32_t diff = howbig - howsmall;
|
||||
return (int32_t)lv_rand(0, diff) + howsmall;
|
||||
}
|
||||
|
||||
static void lv_monkey_timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_timer_get_user_data(timer);
|
||||
lv_indev_data_t * data = &monkey->indev_data;
|
||||
|
||||
switch(lv_indev_get_type(monkey->indev)) {
|
||||
case LV_INDEV_TYPE_POINTER:
|
||||
data->point.x = (int32_t)lv_monkey_random(0, LV_HOR_RES - 1);
|
||||
data->point.y = (int32_t)lv_monkey_random(0, LV_VER_RES - 1);
|
||||
break;
|
||||
case LV_INDEV_TYPE_ENCODER:
|
||||
data->enc_diff = (int16_t)lv_monkey_random(monkey->config.input_range.min, monkey->config.input_range.max);
|
||||
break;
|
||||
case LV_INDEV_TYPE_BUTTON:
|
||||
data->btn_id = (uint32_t)lv_monkey_random(monkey->config.input_range.min, monkey->config.input_range.max);
|
||||
break;
|
||||
case LV_INDEV_TYPE_KEYPAD: {
|
||||
int32_t index = lv_monkey_random(0, sizeof(lv_key_map) / sizeof(lv_key_map[0]) - 1);
|
||||
data->key = lv_key_map[index];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
data->state = lv_monkey_random(0, 100) < 50 ? LV_INDEV_STATE_RELEASED : LV_INDEV_STATE_PRESSED;
|
||||
|
||||
lv_timer_set_period(monkey->timer, lv_monkey_random(monkey->config.period_range.min, monkey->config.period_range.max));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_MONKEY*/
|
||||
119
inc/lvgl/src/debugging/monkey/lv_monkey.h
Normal file
119
inc/lvgl/src/debugging/monkey/lv_monkey.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @file lv_monkey.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_MONKEY_H
|
||||
#define LV_MONKEY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_monkey_t lv_monkey_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
} lv_range_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
} lv_urange_t;
|
||||
|
||||
struct _lv_monkey_config_t {
|
||||
/** Input device type */
|
||||
lv_indev_type_t type;
|
||||
|
||||
/** Monkey execution period */
|
||||
lv_urange_t period_range;
|
||||
|
||||
/** The range of input value */
|
||||
lv_range_t input_range;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize a monkey config with default values
|
||||
* @param config pointer to 'lv_monkey_config_t' variable to initialize
|
||||
*/
|
||||
void lv_monkey_config_init(lv_monkey_config_t * config);
|
||||
|
||||
/**
|
||||
* Create monkey for test
|
||||
* @param config pointer to 'lv_monkey_config_t' variable
|
||||
* @return pointer to the created monkey
|
||||
*/
|
||||
lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config);
|
||||
|
||||
/**
|
||||
* Get monkey input device
|
||||
* @param monkey pointer to a monkey
|
||||
* @return pointer to the input device
|
||||
*/
|
||||
lv_indev_t * lv_monkey_get_indev(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Enable monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @param en set to true to enable
|
||||
*/
|
||||
void lv_monkey_set_enable(lv_monkey_t * monkey, bool en);
|
||||
|
||||
/**
|
||||
* Get whether monkey is enabled
|
||||
* @param monkey pointer to a monkey
|
||||
* @return return true if monkey enabled
|
||||
*/
|
||||
bool lv_monkey_get_enable(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Set the user_data field of the monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @param user_data pointer to the new user_data.
|
||||
*/
|
||||
void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data);
|
||||
|
||||
/**
|
||||
* Get the user_data field of the monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @return the pointer to the user_data of the monkey
|
||||
*/
|
||||
void * lv_monkey_get_user_data(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Delete monkey
|
||||
* @param monkey pointer to monkey
|
||||
*/
|
||||
void lv_monkey_delete(lv_monkey_t * monkey);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_MONKEY*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MONKEY_H*/
|
||||
43
inc/lvgl/src/debugging/monkey/lv_monkey_private.h
Normal file
43
inc/lvgl/src/debugging/monkey/lv_monkey_private.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file lv_monkey_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MONKEY_PRIVATE_H
|
||||
#define LV_MONKEY_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_monkey.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_MONKEY != 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MONKEY_PRIVATE_H*/
|
||||
412
inc/lvgl/src/debugging/sysmon/lv_sysmon.c
Normal file
412
inc/lvgl/src/debugging/sysmon/lv_sysmon.c
Normal file
@@ -0,0 +1,412 @@
|
||||
/**
|
||||
* @file lv_sysmon.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_sysmon_private.h"
|
||||
#include "../../misc/lv_timer_private.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../misc/lv_async.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "../../widgets/label/lv_label.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_SYSMON_REFR_PERIOD_DEF
|
||||
#define LV_SYSMON_REFR_PERIOD_DEF 300 /* ms */
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define sysmon_mem LV_GLOBAL_DEFAULT()->sysmon_mem
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
static void perf_update_timer_cb(lv_timer_t * t);
|
||||
static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void perf_monitor_disp_event_cb(lv_event_t * e);
|
||||
static void perf_dump_info(lv_display_t * disp);
|
||||
static void perf_control(lv_display_t * disp, bool start);
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
static void mem_update_timer_cb(lv_timer_t * t);
|
||||
static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_sysmon_builtin_init(void)
|
||||
{
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
static lv_mem_monitor_t mem_info;
|
||||
lv_subject_init_pointer(&sysmon_mem.subject, &mem_info);
|
||||
sysmon_mem.timer = lv_timer_create(mem_update_timer_cb, LV_SYSMON_REFR_PERIOD_DEF, &mem_info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_sysmon_builtin_deinit(void)
|
||||
{
|
||||
#if LV_USE_MEM_MONITOR
|
||||
lv_timer_delete(sysmon_mem.timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_obj_t * lv_sysmon_create(lv_display_t * disp)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_display_get_layer_sys(disp));
|
||||
lv_obj_set_style_bg_opa(label, LV_OPA_50, 0);
|
||||
lv_obj_set_style_bg_color(label, lv_color_black(), 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_white(), 0);
|
||||
lv_obj_set_style_pad_all(label, 3, 0);
|
||||
lv_label_set_text(label, "?");
|
||||
return label;
|
||||
}
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
void lv_sysmon_show_performance(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->perf_label == NULL) {
|
||||
disp->perf_label = lv_sysmon_create(disp);
|
||||
if(disp->perf_label == NULL) {
|
||||
LV_LOG_WARN("Couldn't create sysmon");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_subject_init_pointer(&disp->perf_sysmon_backend.subject, &disp->perf_sysmon_info);
|
||||
lv_obj_align(disp->perf_label, LV_USE_PERF_MONITOR_POS, 0, 0);
|
||||
lv_subject_add_observer_obj(&disp->perf_sysmon_backend.subject, perf_observer_cb, disp->perf_label, NULL);
|
||||
disp->perf_sysmon_backend.timer = lv_timer_create(perf_update_timer_cb, LV_SYSMON_REFR_PERIOD_DEF, disp);
|
||||
lv_display_add_event_cb(disp, perf_monitor_disp_event_cb, LV_EVENT_ALL, NULL);
|
||||
}
|
||||
|
||||
#if LV_USE_PERF_MONITOR_LOG_MODE
|
||||
lv_obj_add_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
#else
|
||||
lv_obj_remove_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_sysmon_hide_performance(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_add_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void lv_sysmon_performance_dump(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
perf_dump_info(disp);
|
||||
}
|
||||
|
||||
void lv_sysmon_performance_resume(lv_display_t * disp)
|
||||
{
|
||||
perf_control(disp, true);
|
||||
}
|
||||
|
||||
void lv_sysmon_performance_pause(lv_display_t * disp)
|
||||
{
|
||||
perf_control(disp, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
void lv_sysmon_show_memory(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->mem_label == NULL) {
|
||||
disp->mem_label = lv_sysmon_create(disp);
|
||||
if(disp->mem_label == NULL) {
|
||||
LV_LOG_WARN("Couldn't create sysmon");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_align(disp->mem_label, LV_USE_MEM_MONITOR_POS, 0, 0);
|
||||
lv_subject_add_observer_obj(&sysmon_mem.subject, mem_observer_cb, disp->mem_label, NULL);
|
||||
}
|
||||
|
||||
lv_obj_remove_flag(disp->mem_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void lv_sysmon_hide_memory(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_add_flag(disp->mem_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
static void perf_monitor_disp_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_sysmon_perf_info_t * info = &disp->perf_sysmon_info;
|
||||
|
||||
switch(code) {
|
||||
case LV_EVENT_REFR_START:
|
||||
info->measured.refr_interval_sum += lv_tick_elaps(info->measured.refr_start);
|
||||
info->measured.refr_start = lv_tick_get();
|
||||
break;
|
||||
case LV_EVENT_REFR_READY:
|
||||
info->measured.refr_elaps_sum += lv_tick_elaps(info->measured.refr_start);
|
||||
info->measured.refr_cnt++;
|
||||
break;
|
||||
case LV_EVENT_RENDER_START:
|
||||
info->measured.render_in_progress = 1;
|
||||
info->measured.render_start = lv_tick_get();
|
||||
break;
|
||||
case LV_EVENT_RENDER_READY:
|
||||
info->measured.render_in_progress = 0;
|
||||
info->measured.render_elaps_sum += lv_tick_elaps(info->measured.render_start);
|
||||
info->measured.render_cnt++;
|
||||
break;
|
||||
case LV_EVENT_FLUSH_START:
|
||||
case LV_EVENT_FLUSH_WAIT_START:
|
||||
if(info->measured.render_in_progress) {
|
||||
info->measured.flush_in_render_start = lv_tick_get();
|
||||
}
|
||||
else {
|
||||
info->measured.flush_not_in_render_start = lv_tick_get();
|
||||
}
|
||||
break;
|
||||
case LV_EVENT_FLUSH_FINISH:
|
||||
case LV_EVENT_FLUSH_WAIT_FINISH:
|
||||
if(info->measured.render_in_progress) {
|
||||
info->measured.flush_in_render_elaps_sum += lv_tick_elaps(info->measured.flush_in_render_start);
|
||||
}
|
||||
else {
|
||||
info->measured.flush_not_in_render_elaps_sum += lv_tick_elaps(info->measured.flush_not_in_render_start);
|
||||
}
|
||||
break;
|
||||
case LV_EVENT_DELETE:
|
||||
lv_timer_delete(disp->perf_sysmon_backend.timer);
|
||||
lv_subject_deinit(&disp->perf_sysmon_backend.subject);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_dump_info(lv_display_t * disp)
|
||||
{
|
||||
uint32_t LV_SYSMON_GET_IDLE(void);
|
||||
|
||||
lv_sysmon_perf_info_t * info = &disp->perf_sysmon_info;
|
||||
info->calculated.run_cnt++;
|
||||
|
||||
uint32_t time_since_last_report = lv_tick_elaps(info->measured.last_report_timestamp);
|
||||
lv_timer_t * disp_refr_timer = lv_display_get_refr_timer(NULL);
|
||||
uint32_t disp_refr_period = disp_refr_timer ? disp_refr_timer->period : LV_DEF_REFR_PERIOD;
|
||||
|
||||
info->calculated.fps = time_since_last_report ? (1000 * info->measured.refr_cnt / time_since_last_report) : 0;
|
||||
info->calculated.fps = LV_MIN(info->calculated.fps,
|
||||
1000 / disp_refr_period); /*Limit due to possible off-by-one error*/
|
||||
|
||||
info->calculated.cpu = 100 - LV_SYSMON_GET_IDLE();
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
uint32_t LV_SYSMON_GET_PROC_IDLE(void);
|
||||
info->calculated.cpu_proc = 100 - LV_SYSMON_GET_PROC_IDLE();
|
||||
#endif /*LV_SYSMON_PROC_IDLE_AVAILABLE*/
|
||||
info->calculated.refr_avg_time = info->measured.refr_cnt ? (info->measured.refr_elaps_sum / info->measured.refr_cnt) :
|
||||
0;
|
||||
|
||||
info->calculated.flush_avg_time = info->measured.render_cnt ?
|
||||
((info->measured.flush_in_render_elaps_sum + info->measured.flush_not_in_render_elaps_sum)
|
||||
/ info->measured.render_cnt) : 0;
|
||||
/*Flush time was measured in rendering time so subtract it*/
|
||||
info->calculated.render_avg_time = info->measured.render_cnt ? ((info->measured.render_elaps_sum -
|
||||
info->measured.flush_in_render_elaps_sum) /
|
||||
info->measured.render_cnt) : 0;
|
||||
|
||||
info->calculated.cpu_avg_total = ((info->calculated.cpu_avg_total * (info->calculated.run_cnt - 1)) +
|
||||
info->calculated.cpu) / info->calculated.run_cnt;
|
||||
info->calculated.fps_avg_total = ((info->calculated.fps_avg_total * (info->calculated.run_cnt - 1)) +
|
||||
info->calculated.fps) / info->calculated.run_cnt;
|
||||
|
||||
lv_subject_set_pointer(&disp->perf_sysmon_backend.subject, info);
|
||||
|
||||
lv_sysmon_perf_info_t prev_info = *info;
|
||||
lv_memzero(info, sizeof(lv_sysmon_perf_info_t));
|
||||
info->measured.refr_start = prev_info.measured.refr_start;
|
||||
info->calculated.cpu_avg_total = prev_info.calculated.cpu_avg_total;
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
info->calculated.cpu_proc = prev_info.calculated.cpu_proc;
|
||||
#endif /*LV_SYSMON_PROC_IDLE_AVAILABLE*/
|
||||
info->calculated.fps_avg_total = prev_info.calculated.fps_avg_total;
|
||||
info->calculated.run_cnt = prev_info.calculated.run_cnt;
|
||||
|
||||
info->measured.last_report_timestamp = lv_tick_get();
|
||||
}
|
||||
|
||||
static void perf_update_timer_cb(lv_timer_t * t)
|
||||
{
|
||||
lv_display_t * disp = lv_timer_get_user_data(t);
|
||||
|
||||
perf_dump_info(disp);
|
||||
}
|
||||
|
||||
static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
const lv_sysmon_perf_info_t * perf = lv_subject_get_pointer(subject);
|
||||
|
||||
#if LV_USE_PERF_MONITOR_LOG_MODE
|
||||
LV_UNUSED(observer);
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
LV_LOG("sysmon: "
|
||||
"%" LV_PRIu32 " FPS (refr_cnt: %" LV_PRIu32 " | redraw_cnt: %" LV_PRIu32"), "
|
||||
"refr %" LV_PRIu32 "ms (render %" LV_PRIu32 "ms | flush %" LV_PRIu32 "ms), "
|
||||
"CPU (total %" LV_PRIu32 "%% proc %" LV_PRIu32 "%%)\n",
|
||||
perf->calculated.fps, perf->measured.refr_cnt, perf->measured.render_cnt,
|
||||
perf->calculated.refr_avg_time, perf->calculated.render_avg_time, perf->calculated.flush_avg_time,
|
||||
perf->calculated.cpu, perf->calculated.cpu_proc);
|
||||
#else
|
||||
LV_LOG("sysmon: "
|
||||
"%" LV_PRIu32 " FPS (refr_cnt: %" LV_PRIu32 " | redraw_cnt: %" LV_PRIu32"), "
|
||||
"refr %" LV_PRIu32 "ms (render %" LV_PRIu32 "ms | flush %" LV_PRIu32 "ms), "
|
||||
"CPU %" LV_PRIu32 "%%\n",
|
||||
perf->calculated.fps, perf->measured.refr_cnt, perf->measured.render_cnt,
|
||||
perf->calculated.refr_avg_time, perf->calculated.render_avg_time, perf->calculated.flush_avg_time,
|
||||
perf->calculated.cpu);
|
||||
#endif
|
||||
#else
|
||||
lv_obj_t * label = lv_observer_get_target(observer);
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
lv_label_set_text_fmt(
|
||||
label,
|
||||
"%" LV_PRIu32" FPS | CPU (%" LV_PRIu32 "%% | %" LV_PRIu32 "%%)\n"
|
||||
"%" LV_PRIu32" ms (%" LV_PRIu32" | %" LV_PRIu32")",
|
||||
perf->calculated.fps, perf->calculated.cpu, perf->calculated.cpu_proc,
|
||||
perf->calculated.render_avg_time + perf->calculated.flush_avg_time,
|
||||
perf->calculated.render_avg_time, perf->calculated.flush_avg_time
|
||||
);
|
||||
#else
|
||||
lv_label_set_text_fmt(
|
||||
label,
|
||||
"%" LV_PRIu32" FPS, %" LV_PRIu32 "%% CPU\n"
|
||||
"%" LV_PRIu32" ms (%" LV_PRIu32" | %" LV_PRIu32")",
|
||||
perf->calculated.fps, perf->calculated.cpu,
|
||||
perf->calculated.render_avg_time + perf->calculated.flush_avg_time,
|
||||
perf->calculated.render_avg_time, perf->calculated.flush_avg_time
|
||||
);
|
||||
#endif /*LV_SYSMON_PROC_IDLE_AVAILABLE*/
|
||||
#endif /*LV_USE_PERF_MONITOR_LOG_MODE*/
|
||||
}
|
||||
|
||||
static void perf_control(lv_display_t * disp, bool start)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->perf_sysmon_backend.timer == NULL) return;
|
||||
|
||||
if(start) {
|
||||
lv_timer_resume(disp->perf_sysmon_backend.timer);
|
||||
}
|
||||
else {
|
||||
lv_timer_pause(disp->perf_sysmon_backend.timer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
static void mem_update_timer_cb(lv_timer_t * t)
|
||||
{
|
||||
lv_mem_monitor_t * mem_mon = lv_timer_get_user_data(t);
|
||||
lv_mem_monitor(mem_mon);
|
||||
lv_subject_set_pointer(&sysmon_mem.subject, mem_mon);
|
||||
}
|
||||
|
||||
static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_obj_t * label = lv_observer_get_target(observer);
|
||||
const lv_mem_monitor_t * mon = lv_subject_get_pointer(subject);
|
||||
|
||||
size_t used_size = mon->total_size - mon->free_size;
|
||||
size_t used_kb = used_size / 1024;
|
||||
size_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102;
|
||||
size_t max_used_kb = mon->max_used / 1024;
|
||||
size_t max_used_kb_tenth = (mon->max_used - (max_used_kb * 1024)) / 102;
|
||||
lv_label_set_text_fmt(label,
|
||||
"%zu.%zu kB (%d%%)\n"
|
||||
"%zu.%zu kB max, %d%% frag.",
|
||||
used_kb, used_kb_tenth, mon->used_pct,
|
||||
max_used_kb, max_used_kb_tenth,
|
||||
mon->frag_pct);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
113
inc/lvgl/src/debugging/sysmon/lv_sysmon.h
Normal file
113
inc/lvgl/src/debugging/sysmon/lv_sysmon.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @file lv_sysmon.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SYSMON_H
|
||||
#define LV_SYSMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../misc/lv_timer.h"
|
||||
#include "../../core/lv_observer.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
#if LV_USE_LABEL == 0
|
||||
#error "lv_sysmon: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_OBSERVER == 0
|
||||
#error "lv_observer: lv_observer is required. Enable it in lv_conf.h (LV_USE_OBSERVER 1) "
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new system monitor label
|
||||
* @param disp create the sys. mon. on this display's system layer
|
||||
* @return the create label
|
||||
*/
|
||||
lv_obj_t * lv_sysmon_create(lv_display_t * disp);
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
/**
|
||||
* Show system performance monitor: CPU usage and FPS count
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_show_performance(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Hide system performance monitor
|
||||
* @param disp target display, NULL: use the default
|
||||
*/
|
||||
void lv_sysmon_hide_performance(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Dump the FPS data recorded between the last and current dump call.
|
||||
* @param disp target display, NULL: use the default
|
||||
*/
|
||||
void lv_sysmon_performance_dump(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Resume the system performance monitor.
|
||||
* @param disp target display, NULL: use the default
|
||||
*/
|
||||
void lv_sysmon_performance_resume(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Pause the system performance monitor.
|
||||
*
|
||||
* @param disp target display, NULL: use the default
|
||||
* @note When the sysmon is stopped you can use `lv_sysmon_dump_performance` to
|
||||
* get performance information. See `lv_sysmon_dump_performance` for more information.
|
||||
*/
|
||||
void lv_sysmon_performance_pause(lv_display_t * disp);
|
||||
|
||||
|
||||
#endif /*LV_USE_PERF_MONITOR*/
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
/**
|
||||
* Show system memory monitor: used memory and the memory fragmentation
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_show_memory(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Hide system memory monitor
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_hide_memory(lv_display_t * disp);
|
||||
|
||||
#endif /*LV_USE_MEM_MONITOR*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SYSMON_H*/
|
||||
94
inc/lvgl/src/debugging/sysmon/lv_sysmon_private.h
Normal file
94
inc/lvgl/src/debugging/sysmon/lv_sysmon_private.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file lv_sysmon_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SYSMON_PRIVATE_H
|
||||
#define LV_SYSMON_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_sysmon.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_sysmon_backend_data_t {
|
||||
lv_subject_t subject;
|
||||
lv_timer_t * timer;
|
||||
};
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
struct _lv_sysmon_perf_info_t {
|
||||
struct {
|
||||
bool inited;
|
||||
uint32_t refr_start;
|
||||
uint32_t refr_interval_sum;
|
||||
uint32_t refr_elaps_sum;
|
||||
uint32_t refr_cnt;
|
||||
uint32_t render_start;
|
||||
uint32_t render_elaps_sum; /*Contains the flush time too*/
|
||||
uint32_t render_cnt;
|
||||
uint32_t flush_in_render_start;
|
||||
uint32_t flush_in_render_elaps_sum;
|
||||
uint32_t flush_not_in_render_start;
|
||||
uint32_t flush_not_in_render_elaps_sum;
|
||||
uint32_t last_report_timestamp;
|
||||
uint32_t render_in_progress : 1;
|
||||
} measured;
|
||||
|
||||
struct {
|
||||
uint32_t fps;
|
||||
uint32_t cpu;
|
||||
#if LV_SYSMON_PROC_IDLE_AVAILABLE
|
||||
uint32_t cpu_proc; /** The applications idle time percentage */
|
||||
#endif
|
||||
uint32_t refr_avg_time;
|
||||
uint32_t render_avg_time; /**< Pure rendering time without flush time*/
|
||||
uint32_t flush_avg_time; /**< Pure flushing time without rendering time*/
|
||||
uint32_t cpu_avg_total;
|
||||
uint32_t fps_avg_total;
|
||||
uint32_t run_cnt;
|
||||
} calculated;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize built-in system monitor, such as performance and memory monitor.
|
||||
*/
|
||||
void lv_sysmon_builtin_init(void);
|
||||
|
||||
/**
|
||||
* DeInitialize built-in system monitor, such as performance and memory monitor.
|
||||
*/
|
||||
void lv_sysmon_builtin_deinit(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_SYSMON */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SYSMON_PRIVATE_H*/
|
||||
47
inc/lvgl/src/debugging/test/lv_test.h
Normal file
47
inc/lvgl/src/debugging/test/lv_test.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file lv_test.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_H
|
||||
#define LV_TEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#include "lv_test_indev.h"
|
||||
#include "lv_test_display.h"
|
||||
#include "lv_test_fs.h"
|
||||
#include "lv_test_helpers.h"
|
||||
#include "lv_test_screenshot_compare.h"
|
||||
#include "lv_test_indev_gesture.h"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_H*/
|
||||
108
inc/lvgl/src/debugging/test/lv_test_display.c
Normal file
108
inc/lvgl/src/debugging/test/lv_test_display.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file lv_test_display.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_test_display.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../lvgl_private.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void dummy_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
|
||||
static void buf_changed_event_cb(lv_event_t * e);
|
||||
static void delete_event_cb(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define _state LV_GLOBAL_DEFAULT()->test_state
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_display_t * lv_test_display_create(int32_t hor_res, int32_t ver_res)
|
||||
{
|
||||
|
||||
lv_display_t * disp = lv_display_create(hor_res, ver_res);
|
||||
lv_display_set_color_format(disp, LV_COLOR_FORMAT_XRGB8888);
|
||||
|
||||
size_t buf_size = 4 * (hor_res + LV_DRAW_BUF_STRIDE_ALIGN - 1) * ver_res + LV_DRAW_BUF_ALIGN;
|
||||
uint8_t * buf = malloc(buf_size);
|
||||
LV_ASSERT_MALLOC(buf);
|
||||
|
||||
lv_draw_buf_init(&_state.draw_buf, hor_res, ver_res, LV_COLOR_FORMAT_XRGB8888, LV_STRIDE_AUTO, lv_draw_buf_align(buf,
|
||||
LV_COLOR_FORMAT_XRGB8888), buf_size);
|
||||
_state.draw_buf.unaligned_data = buf;
|
||||
lv_display_set_draw_buffers(disp, &_state.draw_buf, NULL);
|
||||
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
|
||||
lv_display_set_flush_cb(disp, dummy_flush_cb);
|
||||
|
||||
lv_display_add_event_cb(disp, buf_changed_event_cb, LV_EVENT_COLOR_FORMAT_CHANGED, NULL);
|
||||
lv_display_add_event_cb(disp, buf_changed_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||
lv_display_add_event_cb(disp, delete_event_cb, LV_EVENT_DELETE, NULL);
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void buf_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_target(e);
|
||||
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||
int32_t hor_res = lv_display_get_original_horizontal_resolution(disp);
|
||||
int32_t ver_res = lv_display_get_original_vertical_resolution(disp);
|
||||
|
||||
free(_state.draw_buf.unaligned_data);
|
||||
|
||||
size_t buf_size = 4 * (hor_res + LV_DRAW_BUF_STRIDE_ALIGN - 1) * ver_res + LV_DRAW_BUF_ALIGN;
|
||||
uint8_t * buf = malloc(buf_size);
|
||||
LV_ASSERT_MALLOC(buf);
|
||||
|
||||
lv_draw_buf_init(&_state.draw_buf, hor_res, ver_res, cf, LV_STRIDE_AUTO, lv_draw_buf_align(buf, cf), buf_size);
|
||||
_state.draw_buf.unaligned_data = buf;
|
||||
lv_display_set_draw_buffers(disp, &_state.draw_buf, NULL);
|
||||
}
|
||||
|
||||
static void delete_event_cb(lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(e);
|
||||
lv_display_t * disp = lv_event_get_target(e);
|
||||
lv_draw_buf_t * draw_buf = lv_display_get_buf_active(disp);
|
||||
free(draw_buf->unaligned_data);
|
||||
|
||||
}
|
||||
|
||||
static void dummy_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p)
|
||||
{
|
||||
LV_UNUSED(area);
|
||||
LV_UNUSED(color_p);
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
55
inc/lvgl/src/debugging/test/lv_test_display.h
Normal file
55
inc/lvgl/src/debugging/test/lv_test_display.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file lv_test_display.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_DISPLAY_H
|
||||
#define LV_TEST_DISPLAY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/***
|
||||
* Create a dummy display for for the tests
|
||||
* @param hor_res the maximal horizontal resolution
|
||||
* @param ver_res the maximal vertical resolution
|
||||
* @return the created display
|
||||
*
|
||||
* @note The resolution can be changed to any smaller values later
|
||||
* using `lv_display_set_resolution`
|
||||
* The color format can be freely changed later using `lv_display_set_color_format`
|
||||
*/
|
||||
lv_display_t * lv_test_display_create(int32_t hor_res, int32_t ver_res);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_DISPLAY_H*/
|
||||
193
inc/lvgl/src/debugging/test/lv_test_fs.c
Normal file
193
inc/lvgl/src/debugging/test/lv_test_fs.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @file lv_test_fs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_test_fs.h"
|
||||
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../misc/lv_fs.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_TEST_FS_LETTER 'T'
|
||||
#define LV_TEST_FS_CACHE_SIZE (512)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
|
||||
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
|
||||
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
|
||||
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
|
||||
static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
|
||||
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);
|
||||
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len);
|
||||
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p);
|
||||
static bool fs_ready(lv_fs_drv_t * drv);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static bool is_ready = true;
|
||||
static lv_fs_drv_t fs_drv;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_test_fs_init(void)
|
||||
{
|
||||
lv_fs_drv_init(&fs_drv);
|
||||
|
||||
/*Set up fields...*/
|
||||
fs_drv.letter = LV_TEST_FS_LETTER;
|
||||
fs_drv.cache_size = LV_TEST_FS_CACHE_SIZE;
|
||||
|
||||
fs_drv.open_cb = fs_open;
|
||||
fs_drv.close_cb = fs_close;
|
||||
fs_drv.read_cb = fs_read;
|
||||
fs_drv.write_cb = fs_write;
|
||||
fs_drv.seek_cb = fs_seek;
|
||||
fs_drv.tell_cb = fs_tell;
|
||||
|
||||
fs_drv.dir_close_cb = fs_dir_close;
|
||||
fs_drv.dir_open_cb = fs_dir_open;
|
||||
fs_drv.dir_read_cb = fs_dir_read;
|
||||
|
||||
fs_drv.ready_cb = fs_ready;
|
||||
|
||||
lv_fs_drv_register(&fs_drv);
|
||||
}
|
||||
|
||||
void lv_test_fs_set_ready(bool ready)
|
||||
{
|
||||
is_ready = ready;
|
||||
}
|
||||
|
||||
void lv_test_fs_clear_open_cb(bool is_clear)
|
||||
{
|
||||
fs_drv.open_cb = is_clear ? NULL : fs_open;
|
||||
}
|
||||
|
||||
void lv_test_fs_clear_close_cb(bool is_clear)
|
||||
{
|
||||
fs_drv.close_cb = is_clear ? NULL : fs_close;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
lv_fs_file_t * file_p = lv_malloc(sizeof(lv_fs_file_t));
|
||||
LV_ASSERT_MALLOC(file_p);
|
||||
if(file_p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = lv_fs_open(file_p, path, mode);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
lv_free(file_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file_p;
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
lv_fs_res_t res = lv_fs_close(file_p);
|
||||
lv_free(file_p);
|
||||
return res;
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
return lv_fs_read(file_p, buf, btr, br);
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
return lv_fs_write(file_p, buf, btw, bw);
|
||||
}
|
||||
|
||||
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);
|
||||
return lv_fs_seek(file_p, pos, whence);
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
return lv_fs_tell(file_p, pos_p);
|
||||
}
|
||||
|
||||
static void * fs_dir_open(lv_fs_drv_t * drv, const char * path)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
lv_fs_dir_t * rddir_p = lv_malloc(sizeof(lv_fs_dir_t));
|
||||
if(rddir_p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_fs_res_t res = lv_fs_dir_open(rddir_p, path);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
lv_free(rddir_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rddir_p;
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
return lv_fs_dir_read(rddir_p, fn, fn_len);
|
||||
}
|
||||
|
||||
static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
lv_fs_res_t res = lv_fs_dir_close(rddir_p);
|
||||
lv_free(rddir_p);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool fs_ready(lv_fs_drv_t * drv)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
return is_ready;
|
||||
}
|
||||
|
||||
#endif/*LV_USE_TEST*/
|
||||
69
inc/lvgl/src/debugging/test/lv_test_fs.h
Normal file
69
inc/lvgl/src/debugging/test/lv_test_fs.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file lv_test_fs.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_FS_H
|
||||
#define LV_TEST_FS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the test file system driver
|
||||
*/
|
||||
void lv_test_fs_init(void);
|
||||
|
||||
/**
|
||||
* Set whether the test file system is ready
|
||||
* @param ready true: ready, false: not ready
|
||||
*/
|
||||
void lv_test_fs_set_ready(bool ready);
|
||||
|
||||
/**
|
||||
* Set whether the open callback of the test file system is cleared
|
||||
* @param is_clear true: clear, false: not clear
|
||||
*/
|
||||
void lv_test_fs_clear_open_cb(bool is_clear);
|
||||
|
||||
/**
|
||||
* Set whether the close callback of the test file system is cleared
|
||||
* @param is_clear true: clear, false: not clear
|
||||
*/
|
||||
void lv_test_fs_clear_close_cb(bool is_clear);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_FS_H*/
|
||||
|
||||
|
||||
60
inc/lvgl/src/debugging/test/lv_test_helpers.c
Normal file
60
inc/lvgl/src/debugging/test/lv_test_helpers.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file lv_test_helpers.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_test_helpers.h"
|
||||
|
||||
#if LV_USE_TEST
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_test_wait(uint32_t ms)
|
||||
{
|
||||
while(ms) {
|
||||
lv_tick_inc(1);
|
||||
lv_timer_handler();
|
||||
ms--;
|
||||
}
|
||||
lv_refr_now(NULL);
|
||||
}
|
||||
|
||||
void lv_test_fast_forward(uint32_t ms)
|
||||
{
|
||||
lv_tick_inc(ms);
|
||||
lv_timer_handler();
|
||||
lv_refr_now(NULL);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
80
inc/lvgl/src/debugging/test/lv_test_helpers.h
Normal file
80
inc/lvgl/src/debugging/test/lv_test_helpers.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @file lv_test_helpers.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_HELPERS_H
|
||||
#define LV_TEST_HELPERS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Emulate a delay. It's not real delay, but it tricks LVGL to think that the
|
||||
* required time has been elapsed.
|
||||
* `lv_timer_handler` is called after each millisecond, meaning all the events
|
||||
* will be fired inside this function.
|
||||
* At the end the animations and display will be also updated.
|
||||
* @param ms the number of milliseconds to pass
|
||||
*/
|
||||
void lv_test_wait(uint32_t ms);
|
||||
|
||||
/**
|
||||
* Emulates some time passing.
|
||||
* Update the animations and the display only once at the end.
|
||||
* @param ms the number of milliseconds to pass
|
||||
*/
|
||||
void lv_test_fast_forward(uint32_t ms);
|
||||
|
||||
#if LV_USE_STDLIB_MALLOC != LV_STDLIB_BUILTIN
|
||||
/* Skip checking heap as we don't have the info available */
|
||||
#define LV_HEAP_CHECK(x) do {} while(0)
|
||||
/* Pick a non-zero value */
|
||||
#define lv_test_get_free_mem() (65536)
|
||||
#else
|
||||
#define LV_HEAP_CHECK(x) x
|
||||
|
||||
static inline size_t lv_test_get_free_mem(void)
|
||||
{
|
||||
lv_mem_monitor_t m1;
|
||||
lv_mem_monitor(&m1);
|
||||
return m1.free_size;
|
||||
}
|
||||
#endif /* LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN */
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define LV_TEST_WIDTH_TO_STRIDE(w, px_size) ((((w) * (px_size) + (LV_DRAW_BUF_STRIDE_ALIGN - 1)) / LV_DRAW_BUF_STRIDE_ALIGN) * LV_DRAW_BUF_STRIDE_ALIGN)
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_HELPERS_H*/
|
||||
212
inc/lvgl/src/debugging/test/lv_test_indev.c
Normal file
212
inc/lvgl/src/debugging/test/lv_test_indev.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* @file lv_test_indev.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_test.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../lvgl_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_test_mouse_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static void lv_test_keypad_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static void lv_test_encoder_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define _state LV_GLOBAL_DEFAULT()->test_state
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_test_indev_create_all(void)
|
||||
{
|
||||
_state.mouse_indev = lv_indev_create();
|
||||
lv_indev_set_type(_state.mouse_indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(_state.mouse_indev, lv_test_mouse_read_cb);
|
||||
|
||||
_state.keypad_indev = lv_indev_create();
|
||||
lv_indev_set_type(_state.keypad_indev, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(_state.keypad_indev, lv_test_keypad_read_cb);
|
||||
|
||||
_state.encoder_indev = lv_indev_create();
|
||||
lv_indev_set_type(_state.encoder_indev, LV_INDEV_TYPE_ENCODER);
|
||||
lv_indev_set_read_cb(_state.encoder_indev, lv_test_encoder_read_cb);
|
||||
}
|
||||
|
||||
void lv_test_indev_delete_all(void)
|
||||
{
|
||||
if(_state.mouse_indev) {
|
||||
lv_indev_delete(_state.mouse_indev);
|
||||
_state.mouse_indev = NULL;
|
||||
}
|
||||
|
||||
if(_state.keypad_indev) {
|
||||
lv_indev_delete(_state.keypad_indev);
|
||||
_state.keypad_indev = NULL;
|
||||
}
|
||||
|
||||
if(_state.encoder_indev) {
|
||||
lv_indev_delete(_state.encoder_indev);
|
||||
_state.encoder_indev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_indev_t * lv_test_indev_get_indev(lv_indev_type_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_INDEV_TYPE_POINTER:
|
||||
return _state.mouse_indev;
|
||||
case LV_INDEV_TYPE_KEYPAD:
|
||||
return _state.keypad_indev;
|
||||
case LV_INDEV_TYPE_ENCODER:
|
||||
return _state.encoder_indev;
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void lv_test_mouse_move_to(int32_t x, int32_t y)
|
||||
{
|
||||
_state.x_act = x;
|
||||
_state.y_act = y;
|
||||
}
|
||||
|
||||
|
||||
void lv_test_mouse_move_to_obj(lv_obj_t * obj)
|
||||
{
|
||||
int32_t x = obj->coords.x1 + lv_obj_get_width(obj) / 2;
|
||||
int32_t y = obj->coords.y1 + lv_obj_get_height(obj) / 2;
|
||||
lv_test_mouse_move_to(x, y);
|
||||
}
|
||||
|
||||
void lv_test_mouse_move_by(int32_t x, int32_t y)
|
||||
{
|
||||
_state.x_act += x;
|
||||
_state.y_act += y;
|
||||
}
|
||||
|
||||
void lv_test_mouse_press(void)
|
||||
{
|
||||
_state.mouse_pressed = true;
|
||||
}
|
||||
|
||||
void lv_test_mouse_release(void)
|
||||
{
|
||||
_state.mouse_pressed = false;
|
||||
}
|
||||
|
||||
void lv_test_mouse_click_at(int32_t x, int32_t y)
|
||||
{
|
||||
lv_test_mouse_release();
|
||||
lv_test_wait(50);
|
||||
lv_test_mouse_move_to(x, y);
|
||||
lv_test_mouse_press();
|
||||
lv_test_wait(50);
|
||||
lv_test_mouse_release();
|
||||
lv_test_wait(50);
|
||||
}
|
||||
|
||||
void lv_test_key_press(uint32_t k)
|
||||
{
|
||||
_state.key_act = k;
|
||||
_state.key_pressed = true;
|
||||
}
|
||||
|
||||
void lv_test_key_release(void)
|
||||
{
|
||||
_state.key_pressed = false;
|
||||
}
|
||||
|
||||
void lv_test_key_hit(uint32_t k)
|
||||
{
|
||||
lv_test_key_release();
|
||||
lv_test_wait(50);
|
||||
lv_test_key_press(k);
|
||||
lv_test_wait(50);
|
||||
lv_test_key_release();
|
||||
lv_test_wait(50);
|
||||
}
|
||||
|
||||
void lv_test_encoder_add_diff(int32_t d)
|
||||
{
|
||||
_state.diff_act += d;
|
||||
}
|
||||
|
||||
void lv_test_encoder_turn(int32_t d)
|
||||
{
|
||||
_state.diff_act += d;
|
||||
lv_test_wait(50);
|
||||
}
|
||||
|
||||
void lv_test_encoder_press(void)
|
||||
{
|
||||
_state.enc_pressed = true;
|
||||
}
|
||||
|
||||
void lv_test_encoder_release(void)
|
||||
{
|
||||
_state.enc_pressed = false;
|
||||
}
|
||||
|
||||
void lv_test_encoder_click(void)
|
||||
{
|
||||
lv_test_encoder_release();
|
||||
lv_test_wait(50);
|
||||
lv_test_encoder_press();
|
||||
lv_test_wait(50);
|
||||
lv_test_encoder_release();
|
||||
lv_test_wait(50);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_test_mouse_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
LV_UNUSED(indev);
|
||||
lv_point_set(&data->point, _state.x_act, _state.y_act);
|
||||
data->state = _state.mouse_pressed ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
|
||||
|
||||
static void lv_test_keypad_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
LV_UNUSED(indev);
|
||||
data->key = _state.key_act;
|
||||
data->state = _state.key_pressed ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
|
||||
|
||||
static void lv_test_encoder_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
LV_UNUSED(indev);
|
||||
data->enc_diff = _state.diff_act;
|
||||
data->state = _state.enc_pressed ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
|
||||
_state.diff_act = 0;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
171
inc/lvgl/src/debugging/test/lv_test_indev.h
Normal file
171
inc/lvgl/src/debugging/test/lv_test_indev.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* @file lv_test_indev.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_INDEV_H
|
||||
#define LV_TEST_INDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a mouse (pointer), keypad, and encoder indevs.
|
||||
* They can be controlled via function calls during the test
|
||||
*/
|
||||
void lv_test_indev_create_all(void);
|
||||
|
||||
/**
|
||||
* Delete all test input devices
|
||||
*/
|
||||
void lv_test_indev_delete_all(void);
|
||||
|
||||
/**
|
||||
* Get one of the indev created in `lv_test_indev_create_all`
|
||||
* @param type type of the indev to get
|
||||
* @return the indev
|
||||
*/
|
||||
lv_indev_t * lv_test_indev_get_indev(lv_indev_type_t type);
|
||||
|
||||
/**
|
||||
* Move the mouse to the given coordinates.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param x the target absolute X coordinate
|
||||
* @param y the target absolute Y coordinate
|
||||
*/
|
||||
void lv_test_mouse_move_to(int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Move the mouse to the center of a widget
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param obj pointer to an widget
|
||||
*/
|
||||
void lv_test_mouse_move_to_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Move the mouse cursor. Keep the pressed or released state
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param x the difference in X to move
|
||||
* @param y the difference in Y to move
|
||||
*/
|
||||
void lv_test_mouse_move_by(int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Make the mouse button pressed.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
*/
|
||||
void lv_test_mouse_press(void);
|
||||
|
||||
/**
|
||||
* Make the mouse button released.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
*/
|
||||
void lv_test_mouse_release(void);
|
||||
|
||||
/**
|
||||
* Emulate a click on a given point.
|
||||
* First set the released state, wait a little, press, wait, and release again.
|
||||
* The wait time is 50ms.
|
||||
* Internally `lv_timer_handler` is called, meaning all the events will be fired inside this function.
|
||||
* @param x the target absolute X coordinate
|
||||
* @param y the target absolute Y coordinate
|
||||
*/
|
||||
void lv_test_mouse_click_at(int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Emulate a key press.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param k the key to press
|
||||
*/
|
||||
void lv_test_key_press(uint32_t k);
|
||||
|
||||
/**
|
||||
* Release the previously press key.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param k the key to press
|
||||
*/
|
||||
void lv_test_key_release(void);
|
||||
|
||||
/**
|
||||
* Emulate a key hit.
|
||||
* First set the released state, wait a little, press, wait, and release again.
|
||||
* The wait time is 50ms.
|
||||
* Internally `lv_timer_handler` is called, meaning all the events will be fired inside this function.
|
||||
* @param k the key to hit
|
||||
*/
|
||||
void lv_test_key_hit(uint32_t k);
|
||||
|
||||
|
||||
/**
|
||||
* Emulate encoder rotation, use positive parameter to rotate to the right
|
||||
* and negative to rotate to the left.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
* @param d number of encoder ticks to emulate
|
||||
*/
|
||||
void lv_test_encoder_add_diff(int32_t d);
|
||||
|
||||
/**
|
||||
* Emulate an encoder turn a wait 50ms. Use positive parameter to rotate to the right
|
||||
* and negative to rotate to the left.
|
||||
* Internally `lv_timer_handler` is called, meaning all the events will be fired inside this function.
|
||||
* @param d number of encoder ticks to emulate
|
||||
*/
|
||||
void lv_test_encoder_turn(int32_t d);
|
||||
|
||||
/**
|
||||
* Emulate an encoder press.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
*/
|
||||
void lv_test_encoder_press(void);
|
||||
|
||||
/**
|
||||
* Emulate an encoder release.
|
||||
* This function doesn't wait, but just changes the state and returns immediately.
|
||||
*/
|
||||
void lv_test_encoder_release(void);
|
||||
|
||||
/**
|
||||
* Emulate am encoder click.
|
||||
* First set the released state, wait a little, press, wait, and release again.
|
||||
* The wait time is 50ms.
|
||||
* Internally `lv_timer_handler` is called, meaning all the events will be fired inside this function.
|
||||
*/
|
||||
void lv_test_encoder_click(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_INDEV_H*/
|
||||
|
||||
|
||||
|
||||
|
||||
141
inc/lvgl/src/debugging/test/lv_test_indev_gesture.c
Normal file
141
inc/lvgl/src/debugging/test/lv_test_indev_gesture.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file lv_test_indev_gesture.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_test.h"
|
||||
#if LV_USE_TEST && LV_USE_GESTURE_RECOGNITION
|
||||
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../lvgl_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define MAX_TOUCH_CNT 2
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_test_gesture_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define _state LV_GLOBAL_DEFAULT()->test_state
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_test_indev_gesture_create(void)
|
||||
{
|
||||
_state.max_touch_cnt = MAX_TOUCH_CNT;
|
||||
_state.touch_data =
|
||||
lv_malloc_zeroed(sizeof(lv_indev_touch_data_t) * _state.max_touch_cnt);
|
||||
if(_state.touch_data == NULL) {
|
||||
LV_LOG_ERROR("lv_indev_touch_data_t malloc failed");
|
||||
}
|
||||
|
||||
_state.gesture_indev = lv_indev_create();
|
||||
lv_indev_set_type(_state.gesture_indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(_state.gesture_indev, lv_test_gesture_read_cb);
|
||||
}
|
||||
|
||||
void lv_test_indev_gesture_delete(void)
|
||||
{
|
||||
if(_state.gesture_indev) {
|
||||
lv_indev_delete(_state.gesture_indev);
|
||||
_state.gesture_indev = NULL;
|
||||
}
|
||||
|
||||
if(_state.touch_data) {
|
||||
lv_free(_state.touch_data);
|
||||
_state.touch_data = NULL;
|
||||
}
|
||||
|
||||
_state.max_touch_cnt = 0;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_test_indev_get_gesture_indev(lv_indev_type_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_INDEV_TYPE_POINTER:
|
||||
return _state.gesture_indev;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_test_gesture_set_pinch_data(lv_point_t point_0, lv_point_t point_1)
|
||||
{
|
||||
_state.touch_data[0].id = 0;
|
||||
_state.touch_data[0].point = point_0;
|
||||
_state.touch_data[1].id = 1;
|
||||
_state.touch_data[1].point = point_1;
|
||||
}
|
||||
|
||||
void lv_test_gesture_pinch_press(void)
|
||||
{
|
||||
_state.touch_data[0].state = LV_INDEV_STATE_PRESSED;
|
||||
_state.touch_data[1].state = LV_INDEV_STATE_PRESSED;
|
||||
}
|
||||
|
||||
void lv_test_gesture_pinch_release(void)
|
||||
{
|
||||
_state.touch_data[0].state = LV_INDEV_STATE_RELEASED;
|
||||
_state.touch_data[1].state = LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
|
||||
void lv_test_gesture_pinch(lv_point_t point_begin_0, lv_point_t point_begin_1,
|
||||
lv_point_t point_end_0, lv_point_t point_end_1)
|
||||
{
|
||||
lv_test_gesture_pinch_release();
|
||||
lv_test_wait(50);
|
||||
lv_test_gesture_set_pinch_data(point_begin_0, point_begin_1);
|
||||
lv_test_gesture_pinch_press();
|
||||
lv_test_wait(50);
|
||||
lv_test_gesture_set_pinch_data(point_end_0, point_end_1);
|
||||
lv_test_wait(80);
|
||||
lv_test_gesture_set_pinch_data(point_end_0, point_end_1);
|
||||
lv_test_wait(80);
|
||||
lv_test_gesture_pinch_release();
|
||||
lv_test_wait(50);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_test_gesture_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
LV_UNUSED(indev);
|
||||
|
||||
lv_indev_gesture_recognizers_update(indev,
|
||||
_state.touch_data,
|
||||
_state.max_touch_cnt);
|
||||
lv_indev_gesture_recognizers_set_data(indev, data);
|
||||
if(_state.touch_data != NULL && _state.max_touch_cnt > 0) {
|
||||
data->point.x = _state.touch_data[0].point.x;
|
||||
data->point.y = _state.touch_data[0].point.y;
|
||||
}
|
||||
else {
|
||||
LV_LOG_ERROR("Invalid touch data or max touch count");
|
||||
data->point.x = 0;
|
||||
data->point.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
93
inc/lvgl/src/debugging/test/lv_test_indev_gesture.h
Normal file
93
inc/lvgl/src/debugging/test/lv_test_indev_gesture.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @file lv_test_indev_gesture.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_INDEV_GESTURE_H
|
||||
#define LV_TEST_INDEV_GESTURE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST && LV_USE_GESTURE_RECOGNITION
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a touch (pointer) indevs.
|
||||
* They can be controlled via function calls during the test
|
||||
*/
|
||||
void lv_test_indev_gesture_create(void);
|
||||
|
||||
/**
|
||||
* Delete the touch (pointer) indevs.
|
||||
*/
|
||||
void lv_test_indev_gesture_delete(void);
|
||||
|
||||
/**
|
||||
* Get one of the indev created in `lv_test_indev_gesture_create`
|
||||
* @param type type of the indev to get
|
||||
* @return the indev
|
||||
*/
|
||||
lv_indev_t * lv_test_indev_get_gesture_indev(lv_indev_type_t type);
|
||||
|
||||
/**
|
||||
* Set two touch points data for pinch gesture
|
||||
* @param point_0 First touch point coordinates
|
||||
* @param point_1 Second touch point coordinates
|
||||
*/
|
||||
void lv_test_gesture_set_pinch_data(lv_point_t point_0, lv_point_t point_1);
|
||||
|
||||
/**
|
||||
* Trigger press state of pinch gesture (both touch points pressed)
|
||||
*/
|
||||
void lv_test_gesture_pinch_press(void);
|
||||
|
||||
/**
|
||||
* Trigger release state of pinch gesture (both touch points released)
|
||||
*/
|
||||
void lv_test_gesture_pinch_release(void);
|
||||
|
||||
/**
|
||||
* Simulate a complete pinch gesture operation
|
||||
* @param point_begin_0 Starting coordinates of first touch point
|
||||
* @param point_begin_1 Starting coordinates of second touch point
|
||||
* @param point_end_0 Ending coordinates of first touch point
|
||||
* @param point_end_1 Ending coordinates of second touch point
|
||||
*/
|
||||
void lv_test_gesture_pinch(lv_point_t point_begin_0, lv_point_t point_begin_1,
|
||||
lv_point_t point_end_0, lv_point_t point_end_1);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST && LV_USE_GESTURE_RECOGNITION*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_INDEV_GESTURE_H*/
|
||||
|
||||
|
||||
|
||||
|
||||
67
inc/lvgl/src/debugging/test/lv_test_private.h
Normal file
67
inc/lvgl/src/debugging/test/lv_test_private.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file lv_test_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_PRIVATE_H
|
||||
#define LV_TEST_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../indev/lv_indev_gesture.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_indev_t * mouse_indev;
|
||||
lv_indev_t * keypad_indev;
|
||||
lv_indev_t * encoder_indev;
|
||||
|
||||
lv_draw_buf_t draw_buf;
|
||||
|
||||
int32_t x_act;
|
||||
int32_t y_act;
|
||||
uint32_t key_act;
|
||||
int32_t diff_act;
|
||||
bool mouse_pressed;
|
||||
bool key_pressed;
|
||||
bool enc_pressed;
|
||||
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
lv_indev_t * gesture_indev;
|
||||
lv_indev_touch_data_t * touch_data;
|
||||
uint8_t max_touch_cnt;
|
||||
#endif
|
||||
} lv_test_state_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*LV_TEST_PRIVATE_H*/
|
||||
348
inc/lvgl/src/debugging/test/lv_test_screenshot_compare.c
Normal file
348
inc/lvgl/src/debugging/test/lv_test_screenshot_compare.c
Normal file
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
* @file lv_test_screenshot_compare.c
|
||||
*
|
||||
* Copyright 2002-2010 Guillaume Cottenceau.
|
||||
*
|
||||
* This software may be freely redistributed under the terms
|
||||
* of the X11 license.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST && defined(LV_USE_TEST_SCREENSHOT_COMPARE) && LV_USE_TEST_SCREENSHOT_COMPARE
|
||||
|
||||
#if LV_USE_LODEPNG == 0
|
||||
#error "lodepng is required for screenshot compare. Enable it in lv_conf.h (LV_USE_LODEPNG 1)"
|
||||
#endif
|
||||
|
||||
#include "../../lvgl.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include "../../libs/lodepng/lodepng.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#define mkdir(pathname, mode) _mkdir(pathname)
|
||||
#define strtok_r strtok_s
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#ifndef REF_IMGS_PATH
|
||||
#define REF_IMGS_PATH ""
|
||||
#endif
|
||||
|
||||
#ifndef REF_IMG_TOLERANCE
|
||||
#define REF_IMG_TOLERANCE 0
|
||||
#endif
|
||||
|
||||
#define ERR_FILE_NOT_FOUND -1
|
||||
#define ERR_PNG -2
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_test_screenshot_result_t screenshot_compare(const char * fn_ref, uint8_t tolerance);
|
||||
static unsigned read_png_file(lv_draw_buf_t ** refr_draw_buf, unsigned * width, unsigned * height,
|
||||
const char * file_name);
|
||||
static unsigned write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name);
|
||||
static void buf_to_xrgb8888(const lv_draw_buf_t * draw_buf, uint8_t * buf_out);
|
||||
static void create_folders_if_needed(const char * path) ;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_test_screenshot_result_t lv_test_screenshot_compare(const char * fn_ref)
|
||||
{
|
||||
|
||||
lv_obj_t * scr = lv_screen_active();
|
||||
lv_obj_invalidate(scr);
|
||||
lv_refr_now(NULL);
|
||||
|
||||
lv_test_screenshot_result_t res;
|
||||
res = screenshot_compare(fn_ref, REF_IMG_TOLERANCE);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Compare the content of the frame buffer with a reference image
|
||||
* @param fn_ref reference image path
|
||||
* @return An element of lv_test_screenshot_result_t
|
||||
*/
|
||||
static lv_test_screenshot_result_t screenshot_compare(const char * fn_ref, uint8_t tolerance)
|
||||
{
|
||||
char fn_ref_full[256];
|
||||
lv_snprintf(fn_ref_full, sizeof(fn_ref_full), "%s%s", REF_IMGS_PATH, fn_ref);
|
||||
|
||||
#if LV_TEST_SCREENSHOT_CREATE_REFERENCE_IMAGE
|
||||
create_folders_if_needed(fn_ref_full);
|
||||
#endif
|
||||
|
||||
lv_draw_buf_t * draw_buf = lv_display_get_buf_active(NULL);
|
||||
|
||||
uint8_t * screen_buf_xrgb8888 = lv_malloc(draw_buf->header.w * draw_buf->header.h * 4);
|
||||
if(!screen_buf_xrgb8888) {
|
||||
LV_LOG_ERROR("Not enough memory to compare display with screenshot");
|
||||
return LV_TEST_SCREENSHOT_RESULT_FAILED;
|
||||
}
|
||||
|
||||
buf_to_xrgb8888(draw_buf, screen_buf_xrgb8888);
|
||||
|
||||
lv_draw_buf_t * ref_draw_buf = NULL;
|
||||
unsigned ref_img_width = 0;
|
||||
unsigned ref_img_height = 0;
|
||||
unsigned res = read_png_file(&ref_draw_buf, &ref_img_width, &ref_img_height, fn_ref_full);
|
||||
if(res) {
|
||||
lv_test_screenshot_result_t comp_res;
|
||||
#if LV_TEST_SCREENSHOT_CREATE_REFERENCE_IMAGE
|
||||
LV_LOG_WARN("%s%s", fn_ref_full, " was not found, creating it now from the rendered screen");
|
||||
write_png_file(screen_buf_xrgb8888, draw_buf->header.w, draw_buf->header.h, fn_ref_full);
|
||||
comp_res = LV_TEST_SCREENSHOT_RESULT_PASSED;
|
||||
#else
|
||||
comp_res = LV_TEST_SCREENSHOT_RESULT_NO_REFERENCE_IMAGE;
|
||||
#endif
|
||||
lv_free(screen_buf_xrgb8888);
|
||||
if(ref_draw_buf) lv_draw_buf_destroy(ref_draw_buf);
|
||||
return comp_res;
|
||||
}
|
||||
|
||||
if(ref_img_width != draw_buf->header.w || ref_img_height != draw_buf->header.h) {
|
||||
LV_LOG_WARN("The dimensions of the rendered and the %s reference image don't match", fn_ref);
|
||||
lv_free(screen_buf_xrgb8888);
|
||||
if(ref_draw_buf) lv_draw_buf_destroy(ref_draw_buf);
|
||||
return LV_TEST_SCREENSHOT_RESULT_FAILED;
|
||||
}
|
||||
|
||||
|
||||
unsigned x, y;
|
||||
bool err = false;
|
||||
for(y = 0; y < ref_img_height; y++) {
|
||||
uint8_t * screen_buf_tmp = screen_buf_xrgb8888 + draw_buf->header.w * 4 * y;
|
||||
uint8_t * ref_row = (uint8_t *)ref_draw_buf->data + y * ref_draw_buf->header.stride;
|
||||
for(x = 0; x < ref_img_width; x++) {
|
||||
uint8_t * ptr_ref = &(ref_row[x * 4]);
|
||||
uint8_t * ptr_act = &screen_buf_tmp[x * 4];
|
||||
|
||||
if(LV_ABS((int32_t) ptr_act[0] - (int32_t) ptr_ref[0]) > tolerance ||
|
||||
LV_ABS((int32_t) ptr_act[1] - (int32_t) ptr_ref[1]) > tolerance ||
|
||||
LV_ABS((int32_t) ptr_act[2] - (int32_t) ptr_ref[2]) > tolerance) {
|
||||
uint32_t act_px = (ptr_act[2] << 16) + (ptr_act[1] << 8) + (ptr_act[0] << 0);
|
||||
uint32_t ref_px = 0;
|
||||
memcpy(&ref_px, ptr_ref, 3);
|
||||
LV_LOG("\nScreenshot compare error\n"
|
||||
" - File: %s\n"
|
||||
" - At x:%d, y:%d.\n"
|
||||
" - Expected: %X\n"
|
||||
" - Actual: %X\n"
|
||||
" - Tolerance: %d\n",
|
||||
fn_ref_full, x, y, ref_px, act_px, tolerance);
|
||||
err = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(err) break;
|
||||
}
|
||||
|
||||
if(err) {
|
||||
char fn_ref_no_ext[128];
|
||||
lv_strlcpy(fn_ref_no_ext, fn_ref, sizeof(fn_ref_no_ext));
|
||||
fn_ref_no_ext[strlen(fn_ref_no_ext) - 4] = '\0';
|
||||
|
||||
char fn_err_full[256];
|
||||
lv_snprintf(fn_err_full, sizeof(fn_err_full), "%s%s_err.png", REF_IMGS_PATH, fn_ref_no_ext);
|
||||
|
||||
write_png_file(screen_buf_xrgb8888, draw_buf->header.w, draw_buf->header.h, fn_err_full);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
lv_free(screen_buf_xrgb8888);
|
||||
if(ref_draw_buf) lv_draw_buf_destroy(ref_draw_buf);
|
||||
return err ? LV_TEST_SCREENSHOT_RESULT_FAILED : LV_TEST_SCREENSHOT_RESULT_PASSED;
|
||||
|
||||
}
|
||||
|
||||
static unsigned read_png_file(lv_draw_buf_t ** refr_draw_buf, unsigned * width, unsigned * height,
|
||||
const char * file_name)
|
||||
{
|
||||
unsigned error = lodepng_decode32_file((void *)refr_draw_buf, width, height, file_name);
|
||||
if(error) LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
static unsigned write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name)
|
||||
{
|
||||
unsigned error = lodepng_encode32_file(file_name, raw_img, width, height);
|
||||
if(error) LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
static void buf_to_xrgb8888(const lv_draw_buf_t * draw_buf, uint8_t * buf_out)
|
||||
{
|
||||
uint32_t stride = draw_buf->header.stride;
|
||||
lv_color_format_t cf_in = draw_buf->header.cf;
|
||||
const uint8_t * buf_in = draw_buf->data;
|
||||
|
||||
if(cf_in == LV_COLOR_FORMAT_RGB565 || cf_in == LV_COLOR_FORMAT_RGB565_SWAPPED) {
|
||||
if(cf_in == LV_COLOR_FORMAT_RGB565_SWAPPED) {
|
||||
lv_draw_sw_rgb565_swap(draw_buf->data, draw_buf->header.w * draw_buf->header.h);
|
||||
}
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
const lv_color16_t * c16 = (const lv_color16_t *)&buf_in[x * 2];
|
||||
|
||||
buf_out[x * 4 + 3] = 0xff;
|
||||
buf_out[x * 4 + 2] = (c16->blue * 2106) >> 8; /*To make it rounded*/
|
||||
buf_out[x * 4 + 1] = (c16->green * 1037) >> 8;
|
||||
buf_out[x * 4 + 0] = (c16->red * 2106) >> 8;
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
else if(cf_in == LV_COLOR_FORMAT_ARGB8888 || cf_in == LV_COLOR_FORMAT_XRGB8888 ||
|
||||
cf_in == LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED) {
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
buf_out[x * 4 + 3] = buf_in[x * 4 + 3];
|
||||
buf_out[x * 4 + 2] = buf_in[x * 4 + 0];
|
||||
buf_out[x * 4 + 1] = buf_in[x * 4 + 1];
|
||||
buf_out[x * 4 + 0] = buf_in[x * 4 + 2];
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
else if(cf_in == LV_COLOR_FORMAT_RGB888) {
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
buf_out[x * 4 + 3] = 0xff;
|
||||
buf_out[x * 4 + 2] = buf_in[x * 3 + 0];
|
||||
buf_out[x * 4 + 1] = buf_in[x * 3 + 1];
|
||||
buf_out[x * 4 + 0] = buf_in[x * 3 + 2];
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
else if(cf_in == LV_COLOR_FORMAT_L8) {
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
buf_out[x * 4 + 3] = 0xff;
|
||||
buf_out[x * 4 + 2] = buf_in[x];
|
||||
buf_out[x * 4 + 1] = buf_in[x];
|
||||
buf_out[x * 4 + 0] = buf_in[x];
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
else if(cf_in == LV_COLOR_FORMAT_AL88) {
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
buf_out[x * 4 + 3] = buf_in[x * 2 + 1];
|
||||
buf_out[x * 4 + 2] = buf_in[x * 2 + 0];
|
||||
buf_out[x * 4 + 1] = buf_in[x * 2 + 0];
|
||||
buf_out[x * 4 + 0] = buf_in[x * 2 + 0];
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
else if(cf_in == LV_COLOR_FORMAT_I1) {
|
||||
buf_in += 8;
|
||||
uint32_t y;
|
||||
for(y = 0; y < draw_buf->header.h; y++) {
|
||||
uint32_t x;
|
||||
for(x = 0; x < draw_buf->header.w; x++) {
|
||||
const uint8_t byte = buf_in[x / 8] ;
|
||||
const uint8_t bit_pos = x % 8;
|
||||
const uint8_t pixel = (byte >> (7 - bit_pos)) & 0x01;
|
||||
|
||||
buf_out[x * 4 + 3] = 0xff;
|
||||
buf_out[x * 4 + 2] = pixel ? 0xff : 0x00;
|
||||
buf_out[x * 4 + 1] = pixel ? 0xff : 0x00;
|
||||
buf_out[x * 4 + 0] = pixel ? 0xff : 0x00;
|
||||
}
|
||||
|
||||
buf_in += stride;
|
||||
buf_out += draw_buf->header.w * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void create_folders_if_needed(const char * path)
|
||||
{
|
||||
char * ptr;
|
||||
char * path_copy = lv_strdup(path);
|
||||
if(path_copy == NULL) {
|
||||
LV_LOG_ERROR("Error duplicating path");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char * token = strtok_r(path_copy, "/", &ptr);
|
||||
char current_path[1024] = {'\0'}; /* Adjust the size as needed */
|
||||
|
||||
while(token && ptr && *ptr != '\0') {
|
||||
lv_strcat(current_path, token);
|
||||
lv_strcat(current_path, "/");
|
||||
|
||||
int mkdir_retval = mkdir(current_path, 0777);
|
||||
if(mkdir_retval == 0) {
|
||||
LV_LOG_INFO("Created folder: %s\n", current_path);
|
||||
}
|
||||
else if(errno != EEXIST) {
|
||||
perror("Error creating folder");
|
||||
lv_free(path_copy);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, "/", &ptr);
|
||||
}
|
||||
|
||||
lv_free(path_copy);
|
||||
}
|
||||
|
||||
#endif
|
||||
79
inc/lvgl/src/debugging/test/lv_test_screenshot_compare.h
Normal file
79
inc/lvgl/src/debugging/test/lv_test_screenshot_compare.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_test_screenshot_compare.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEST_SCREENSHOT_COMPARE_H
|
||||
#define LV_TEST_SCREENSHOT_COMPARE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_TEST && defined(LV_USE_TEST_SCREENSHOT_COMPARE) && LV_USE_TEST_SCREENSHOT_COMPARE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return value of `lv_test_screenshot_compare`
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* The screenshot is different than the reference image
|
||||
*/
|
||||
LV_TEST_SCREENSHOT_RESULT_FAILED,
|
||||
|
||||
/**
|
||||
* The screenshot is the same as the reference image.
|
||||
* It is also returned if `LV_TEST_SCREENSHOT_CREATE_REFERENCE_IMAGE` is enabled
|
||||
* and the reference image was missing.
|
||||
*/
|
||||
LV_TEST_SCREENSHOT_RESULT_PASSED,
|
||||
|
||||
/**
|
||||
* If `LV_TEST_SCREENSHOT_CREATE_REFERENCE_IMAGE` is not enabled
|
||||
* and the reference image is missing.
|
||||
*/
|
||||
LV_TEST_SCREENSHOT_RESULT_NO_REFERENCE_IMAGE,
|
||||
|
||||
} lv_test_screenshot_result_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Compare the current content of the test screen with a reference PNG image
|
||||
* - If the reference image is not found it will be created automatically from the rendered screen.
|
||||
* - If the compare fails an `<image_name>_err.png` file will be created with the rendered content next to the reference image.
|
||||
*
|
||||
* It requires lodepng.
|
||||
*
|
||||
* @param fn_ref path to the reference image. Will be appended to REF_IMGS_PATH if set.
|
||||
* @return An element of `lv_test_screenshot_result_t`
|
||||
* @note This function assumes that the default display is the test display that was created by
|
||||
* `lv_test_display_create()`
|
||||
*/
|
||||
lv_test_screenshot_result_t lv_test_screenshot_compare(const char * fn_ref);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TEST_SCREENSHOT_COMPARE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEST_SCREENSHOT_COMPARE_H*/
|
||||
1352
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite.h
Normal file
1352
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite.h
Normal file
File diff suppressed because it is too large
Load Diff
162
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite_matrix.c
Normal file
162
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite_matrix.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file vg_lite_matrix.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define VG_SW_BLIT_PRECISION_OPT 1
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
vg_lite_error_t vg_lite_identity(vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set identify matrix. */
|
||||
matrix->m[0][0] = 1.0f;
|
||||
matrix->m[0][1] = 0.0f;
|
||||
matrix->m[0][2] = 0.0f;
|
||||
matrix->m[1][0] = 0.0f;
|
||||
matrix->m[1][1] = 1.0f;
|
||||
matrix->m[1][2] = 0.0f;
|
||||
matrix->m[2][0] = 0.0f;
|
||||
matrix->m[2][1] = 0.0f;
|
||||
matrix->m[2][2] = 1.0f;
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->scaleX = 1.0f;
|
||||
matrix->scaleY = 1.0f;
|
||||
matrix->angle = 0.0f;
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
|
||||
{
|
||||
vg_lite_matrix_t temp;
|
||||
int row, column;
|
||||
|
||||
/* Process all rows. */
|
||||
for(row = 0; row < 3; row++) {
|
||||
/* Process all columns. */
|
||||
for(column = 0; column < 3; column++) {
|
||||
/* Compute matrix entry. */
|
||||
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
|
||||
+ (matrix->m[row][1] * mult->m[1][column])
|
||||
+ (matrix->m[row][2] * mult->m[2][column]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy temporary matrix into result. */
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
memcpy(matrix, &temp, sizeof(vg_lite_float_t) * 9);
|
||||
#else
|
||||
memcpy(matrix, &temp, sizeof(temp));
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_translate(vg_lite_float_t x, vg_lite_float_t y, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set translation matrix. */
|
||||
vg_lite_matrix_t t = { { {1.0f, 0.0f, x},
|
||||
{0.0f, 1.0f, y},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &t);
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_scale(vg_lite_float_t scale_x, vg_lite_float_t scale_y, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set scale matrix. */
|
||||
vg_lite_matrix_t s = { { {scale_x, 0.0f, 0.0f},
|
||||
{0.0f, scale_y, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &s);
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->scaleX = matrix->scaleX * scale_x;
|
||||
matrix->scaleY = matrix->scaleY * scale_y;
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_rotate(vg_lite_float_t degrees, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Convert degrees into radians. */
|
||||
vg_lite_float_t angle = (degrees / 180.0f) * 3.141592654f;
|
||||
|
||||
/* Compute cosine and sine values. */
|
||||
vg_lite_float_t cos_angle = cosf(angle);
|
||||
vg_lite_float_t sin_angle = sinf(angle);
|
||||
|
||||
/* Set rotation matrix. */
|
||||
vg_lite_matrix_t r = { { {cos_angle, -sin_angle, 0.0f},
|
||||
{sin_angle, cos_angle, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &r);
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->angle = matrix->angle + degrees;
|
||||
if(matrix->angle >= 360) {
|
||||
vg_lite_uint32_t count = (vg_lite_uint32_t)matrix->angle / 360;
|
||||
matrix->angle = matrix->angle - count * 360;
|
||||
}
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_VG_LITE_THORVG*/
|
||||
3076
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite_tvg.cpp
Normal file
3076
inc/lvgl/src/debugging/vg_lite_tvg/vg_lite_tvg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1562
inc/lvgl/src/display/lv_display.c
Normal file
1562
inc/lvgl/src/display/lv_display.c
Normal file
File diff suppressed because it is too large
Load Diff
762
inc/lvgl/src/display/lv_display.h
Normal file
762
inc/lvgl/src/display/lv_display.h
Normal file
@@ -0,0 +1,762 @@
|
||||
/**
|
||||
* @file lv_display.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DISPLAY_H
|
||||
#define LV_DISPLAY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_event.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#ifndef LV_ATTRIBUTE_FLUSH_READY
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_DISPLAY_ROTATION_0 = 0,
|
||||
LV_DISPLAY_ROTATION_90,
|
||||
LV_DISPLAY_ROTATION_180,
|
||||
LV_DISPLAY_ROTATION_270
|
||||
} lv_display_rotation_t;
|
||||
|
||||
typedef enum {
|
||||
/**
|
||||
* Use the buffer(s) to render the screen is smaller parts.
|
||||
* This way the buffers can be smaller then the display to save RAM. At least 1/10 screen size buffer(s) are recommended.
|
||||
*/
|
||||
LV_DISPLAY_RENDER_MODE_PARTIAL,
|
||||
|
||||
/**
|
||||
* The buffer(s) has to be screen sized and LVGL will render into the correct location of the buffer.
|
||||
* This way the buffer always contain the whole image. Only the changed ares will be updated.
|
||||
* With 2 buffers the buffers' content are kept in sync automatically and in flush_cb only address change is required.
|
||||
*/
|
||||
LV_DISPLAY_RENDER_MODE_DIRECT,
|
||||
|
||||
/**
|
||||
* Always redraw the whole screen even if only one pixel has been changed.
|
||||
* With 2 buffers in flush_cb only an address change is required.
|
||||
*/
|
||||
LV_DISPLAY_RENDER_MODE_FULL,
|
||||
} lv_display_render_mode_t;
|
||||
|
||||
typedef enum {
|
||||
LV_SCREEN_LOAD_ANIM_NONE,
|
||||
LV_SCREEN_LOAD_ANIM_OVER_LEFT,
|
||||
LV_SCREEN_LOAD_ANIM_OVER_RIGHT,
|
||||
LV_SCREEN_LOAD_ANIM_OVER_TOP,
|
||||
LV_SCREEN_LOAD_ANIM_OVER_BOTTOM,
|
||||
LV_SCREEN_LOAD_ANIM_MOVE_LEFT,
|
||||
LV_SCREEN_LOAD_ANIM_MOVE_RIGHT,
|
||||
LV_SCREEN_LOAD_ANIM_MOVE_TOP,
|
||||
LV_SCREEN_LOAD_ANIM_MOVE_BOTTOM,
|
||||
LV_SCREEN_LOAD_ANIM_FADE_IN,
|
||||
LV_SCREEN_LOAD_ANIM_FADE_ON = LV_SCREEN_LOAD_ANIM_FADE_IN, /*For backward compatibility*/
|
||||
LV_SCREEN_LOAD_ANIM_FADE_OUT,
|
||||
LV_SCREEN_LOAD_ANIM_OUT_LEFT,
|
||||
LV_SCREEN_LOAD_ANIM_OUT_RIGHT,
|
||||
LV_SCREEN_LOAD_ANIM_OUT_TOP,
|
||||
LV_SCREEN_LOAD_ANIM_OUT_BOTTOM,
|
||||
} lv_screen_load_anim_t;
|
||||
|
||||
typedef void (*lv_display_flush_cb_t)(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
|
||||
typedef void (*lv_display_flush_wait_cb_t)(lv_display_t * disp);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new display with the given resolution
|
||||
* @param hor_res horizontal resolution in pixels
|
||||
* @param ver_res vertical resolution in pixels
|
||||
* @return pointer to a display object or `NULL` on error
|
||||
*/
|
||||
lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res);
|
||||
|
||||
/**
|
||||
* Remove a display
|
||||
* @param disp pointer to display
|
||||
*/
|
||||
void lv_display_delete(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Set a default display. The new screens will be created on it by default.
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_display_set_default(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the default display
|
||||
* @return pointer to the default display
|
||||
*/
|
||||
lv_display_t * lv_display_get_default(void);
|
||||
|
||||
/**
|
||||
* Get the next display.
|
||||
* @param disp pointer to the current display. NULL to initialize.
|
||||
* @return the next display or NULL if no more. Gives the first display when the parameter is NULL.
|
||||
*/
|
||||
lv_display_t * lv_display_get_next(lv_display_t * disp);
|
||||
|
||||
/*---------------------
|
||||
* RESOLUTION
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Sets the resolution of a display. `LV_EVENT_RESOLUTION_CHANGED` event will be sent.
|
||||
* Here the native resolution of the device should be set. If the display will be rotated later with
|
||||
* `lv_display_set_rotation` LVGL will swap the hor. and ver. resolution automatically.
|
||||
* @param disp pointer to a display
|
||||
* @param hor_res the new horizontal resolution
|
||||
* @param ver_res the new vertical resolution
|
||||
*/
|
||||
void lv_display_set_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res);
|
||||
|
||||
/**
|
||||
* It's not mandatory to use the whole display for LVGL, however in some cases physical resolution is important.
|
||||
* For example the touchpad still sees whole resolution and the values needs to be converted
|
||||
* to the active LVGL display area.
|
||||
* @param disp pointer to a display
|
||||
* @param hor_res the new physical horizontal resolution, or -1 to assume it's the same as the normal hor. res.
|
||||
* @param ver_res the new physical vertical resolution, or -1 to assume it's the same as the normal hor. res.
|
||||
*/
|
||||
void lv_display_set_physical_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res);
|
||||
|
||||
/**
|
||||
* If physical resolution is not the same as the normal resolution
|
||||
* the offset of the active display area can be set here.
|
||||
* @param disp pointer to a display
|
||||
* @param x X offset
|
||||
* @param y Y offset
|
||||
*/
|
||||
void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Set the rotation of this display. LVGL will swap the horizontal and vertical resolutions internally.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @param rotation `LV_DISPLAY_ROTATION_0/90/180/270`
|
||||
*/
|
||||
void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation);
|
||||
|
||||
/**
|
||||
* Use matrix rotation for the display. This function is depended on `LV_DRAW_TRANSFORM_USE_MATRIX`
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @param enable true: enable matrix rotation, false: disable
|
||||
*/
|
||||
void lv_display_set_matrix_rotation(lv_display_t * disp, bool enable);
|
||||
|
||||
/**
|
||||
* Set the DPI (dot per inch) of the display.
|
||||
* dpi = sqrt(hor_res^2 + ver_res^2) / diagonal"
|
||||
* @param disp pointer to a display
|
||||
* @param dpi the new DPI
|
||||
*/
|
||||
void lv_display_set_dpi(lv_display_t * disp, int32_t dpi);
|
||||
|
||||
/**
|
||||
* Get the horizontal resolution of a display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the horizontal resolution of the display.
|
||||
*/
|
||||
int32_t lv_display_get_horizontal_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the vertical resolution of a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the vertical resolution of the display
|
||||
*/
|
||||
int32_t lv_display_get_vertical_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the original horizontal resolution of a display without considering rotation
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the horizontal resolution of the display.
|
||||
*/
|
||||
int32_t lv_display_get_original_horizontal_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the original vertical resolution of a display without considering rotation
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the vertical resolution of the display
|
||||
*/
|
||||
int32_t lv_display_get_original_vertical_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the physical horizontal resolution of a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the physical horizontal resolution of the display
|
||||
*/
|
||||
int32_t lv_display_get_physical_horizontal_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the physical vertical resolution of a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the physical vertical resolution of the display
|
||||
*/
|
||||
int32_t lv_display_get_physical_vertical_resolution(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the horizontal offset from the full / physical display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the horizontal offset from the physical display
|
||||
*/
|
||||
int32_t lv_display_get_offset_x(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the vertical offset from the full / physical display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the horizontal offset from the physical display
|
||||
*/
|
||||
int32_t lv_display_get_offset_y(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the current rotation of this display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return the current rotation
|
||||
*/
|
||||
lv_display_rotation_t lv_display_get_rotation(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get if matrix rotation is enabled for a display or not
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return true: matrix rotation is enabled; false: disabled
|
||||
*/
|
||||
bool lv_display_get_matrix_rotation(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the DPI of the display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return dpi of the display
|
||||
*/
|
||||
int32_t lv_display_get_dpi(const lv_display_t * disp);
|
||||
|
||||
/*---------------------
|
||||
* BUFFERING
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Set the buffers for a display, similarly to `lv_display_set_draw_buffers`, but accept the raw buffer pointers.
|
||||
* For DIRECT/FULL rending modes, the buffer size must be at least
|
||||
* `hor_res * ver_res * lv_color_format_get_size(lv_display_get_color_format(disp))`
|
||||
* @param disp pointer to a display
|
||||
* @param buf1 first buffer
|
||||
* @param buf2 second buffer (can be `NULL`)
|
||||
* @param buf_size buffer size in byte
|
||||
* @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL
|
||||
*/
|
||||
void lv_display_set_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size,
|
||||
lv_display_render_mode_t render_mode);
|
||||
|
||||
/**
|
||||
* Set the frame buffers for a display, similarly to `lv_display_set_buffers`, but allow
|
||||
* for a custom stride as required by a display controller.
|
||||
* This allows the frame buffers to have a stride alignment different from the rest of
|
||||
* the buffers`
|
||||
* @param disp pointer to a display
|
||||
* @param buf1 first buffer
|
||||
* @param buf2 second buffer (can be `NULL`)
|
||||
* @param buf_size buffer size in byte
|
||||
* @param stride buffer stride in bytes
|
||||
* @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL
|
||||
*/
|
||||
void lv_display_set_buffers_with_stride(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size,
|
||||
uint32_t stride, lv_display_render_mode_t render_mode);
|
||||
|
||||
/**
|
||||
* Set the buffers for a display, accept a draw buffer pointer.
|
||||
* Normally use `lv_display_set_buffers` is enough for most cases.
|
||||
* Use this function when an existing lv_draw_buf_t is available.
|
||||
* @param disp pointer to a display
|
||||
* @param buf1 first buffer
|
||||
* @param buf2 second buffer (can be `NULL`)
|
||||
*/
|
||||
void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2);
|
||||
|
||||
/**
|
||||
* Set the third draw buffer for a display.
|
||||
* @param disp pointer to a display
|
||||
* @param buf3 third buffer
|
||||
*/
|
||||
void lv_display_set_3rd_draw_buffer(lv_display_t * disp, lv_draw_buf_t * buf3);
|
||||
|
||||
/**
|
||||
* Set display render mode
|
||||
* @param disp pointer to a display
|
||||
* @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL
|
||||
*/
|
||||
void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode);
|
||||
|
||||
/**
|
||||
* Set the flush callback which will be called to copy the rendered image to the display.
|
||||
* @param disp pointer to a display
|
||||
* @param flush_cb the flush callback (`px_map` contains the rendered image as raw pixel map and it should be copied to `area` on the display)
|
||||
*/
|
||||
void lv_display_set_flush_cb(lv_display_t * disp, lv_display_flush_cb_t flush_cb);
|
||||
|
||||
/**
|
||||
* Set a callback to be used while LVGL is waiting flushing to be finished.
|
||||
* It can do any complex logic to wait, including semaphores, mutexes, polling flags, etc.
|
||||
* If not set the `disp->flushing` flag is used which can be cleared with `lv_display_flush_ready()`
|
||||
* @param disp pointer to a display
|
||||
* @param wait_cb a callback to call while LVGL is waiting for flush ready.
|
||||
* If NULL `lv_display_flush_ready()` can be used to signal that flushing is ready.
|
||||
*/
|
||||
void lv_display_set_flush_wait_cb(lv_display_t * disp, lv_display_flush_wait_cb_t wait_cb);
|
||||
|
||||
/**
|
||||
* Set the color format of the display.
|
||||
* @param disp pointer to a display
|
||||
* @param color_format Possible values are
|
||||
* - LV_COLOR_FORMAT_RGB565
|
||||
* - LV_COLOR_FORMAT_RGB888
|
||||
* - LV_COLOR_FORMAT_XRGB888
|
||||
* - LV_COLOR_FORMAT_ARGB888
|
||||
*@note To change the endianness of the rendered image in case of RGB565 format
|
||||
* (i.e. swap the 2 bytes) call `lv_draw_sw_rgb565_swap` in the flush_cb
|
||||
*/
|
||||
void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_format);
|
||||
|
||||
/**
|
||||
* Get the color format of the display
|
||||
* @param disp pointer to a display
|
||||
* @return the color format
|
||||
*/
|
||||
lv_color_format_t lv_display_get_color_format(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Set the number of tiles for parallel rendering.
|
||||
* @param disp pointer to a display
|
||||
* @param tile_cnt number of tiles (1 =< tile_cnt < 256)
|
||||
*/
|
||||
void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt);
|
||||
|
||||
/**
|
||||
* Get the number of tiles used for parallel rendering
|
||||
* @param disp pointer to a display
|
||||
* @return number of tiles
|
||||
*/
|
||||
uint32_t lv_display_get_tile_cnt(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Disabling anti-aliasing is not supported since v9. This function will be removed.
|
||||
* Enable anti-aliasing for the render engine
|
||||
* @param disp pointer to a display
|
||||
* @param en true/false
|
||||
*/
|
||||
void lv_display_set_antialiasing(lv_display_t * disp, bool en);
|
||||
|
||||
/**
|
||||
* Get if anti-aliasing is enabled for a display or not
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
* @return true/false
|
||||
*/
|
||||
bool lv_display_get_antialiasing(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Call from the display driver when the flushing is finished
|
||||
* @param disp pointer to display whose `flush_cb` was called
|
||||
*/
|
||||
LV_ATTRIBUTE_FLUSH_READY void lv_display_flush_ready(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Tell if it's the last area of the refreshing process.
|
||||
* Can be called from `flush_cb` to execute some special display refreshing if needed when all areas area flushed.
|
||||
* @param disp pointer to display
|
||||
* @return true: it's the last area to flush;
|
||||
* false: there are other areas too which will be refreshed soon
|
||||
*/
|
||||
LV_ATTRIBUTE_FLUSH_READY bool lv_display_flush_is_last(lv_display_t * disp);
|
||||
|
||||
bool lv_display_is_double_buffered(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get display render mode
|
||||
* @param disp pointer to a display
|
||||
* @return display's render mode (LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL)
|
||||
*/
|
||||
lv_display_render_mode_t lv_display_get_render_mode(lv_display_t * disp);
|
||||
|
||||
/*---------------------
|
||||
* SCREENS
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Return a pointer to the active screen on a display
|
||||
* @param disp pointer to display which active screen should be get.
|
||||
* (NULL to use the default screen)
|
||||
* @return pointer to the active screen object (loaded by 'lv_screen_load()')
|
||||
*/
|
||||
lv_obj_t * lv_display_get_screen_active(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Return with a pointer to the previous screen. Only used during screen transitions.
|
||||
* @param disp pointer to display which previous screen should be get.
|
||||
* (NULL to use the default screen)
|
||||
* @return pointer to the previous screen object or NULL if not used now
|
||||
*/
|
||||
lv_obj_t * lv_display_get_screen_prev(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Return the screen that is currently being loaded by the display
|
||||
* @param disp pointer to a display object (NULL to use the default screen)
|
||||
* @return pointer to the screen being loaded or NULL if no screen is currently being loaded
|
||||
*/
|
||||
lv_obj_t * lv_display_get_screen_loading(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Return the top layer. The top layer is the same on all screens and it is above the normal screen layer.
|
||||
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
|
||||
* @return pointer to the top layer object
|
||||
*/
|
||||
lv_obj_t * lv_display_get_layer_top(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Return the sys. layer. The system layer is the same on all screen and it is above the normal screen and the top layer.
|
||||
* @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen)
|
||||
* @return pointer to the sys layer object
|
||||
*/
|
||||
lv_obj_t * lv_display_get_layer_sys(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Return the bottom layer. The bottom layer is the same on all screen and it is under the normal screen layer.
|
||||
* It's visible only if the screen is transparent.
|
||||
* @param disp pointer to display (NULL to use the default screen)
|
||||
* @return pointer to the bottom layer object
|
||||
*/
|
||||
lv_obj_t * lv_display_get_layer_bottom(lv_display_t * disp);
|
||||
|
||||
|
||||
#if LV_USE_OBJ_NAME
|
||||
|
||||
/**
|
||||
* Get screen by its name on a display. The name should be set by
|
||||
* `lv_obj_set_name()` or `lv_obj_set_name_static()`.
|
||||
* @param disp pointer to a display or NULL to use default display
|
||||
* @param screen_name name of the screen to get
|
||||
* @return pointer to the screen, or NULL if not found.
|
||||
*/
|
||||
lv_obj_t * lv_display_get_screen_by_name(const lv_display_t * disp, const char * screen_name);
|
||||
|
||||
#endif /*LV_USE_OBJ_NAME*/
|
||||
|
||||
/**
|
||||
* Load a screen on the default display
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_screen_load(struct _lv_obj_t * scr);
|
||||
|
||||
/**
|
||||
* Switch screen with animation
|
||||
* @param scr pointer to the new screen to load
|
||||
* @param anim_type type of the animation from `lv_screen_load_anim_t`, e.g. `LV_SCREEN_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
|
||||
*/
|
||||
void lv_screen_load_anim(lv_obj_t * scr, lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay,
|
||||
bool auto_del);
|
||||
|
||||
/**
|
||||
* Get the active screen of the default display
|
||||
* @return pointer to the active screen
|
||||
*/
|
||||
lv_obj_t * lv_screen_active(void);
|
||||
|
||||
/**
|
||||
* Get the top layer of the default display
|
||||
* @return pointer to the top layer
|
||||
*/
|
||||
lv_obj_t * lv_layer_top(void);
|
||||
|
||||
/**
|
||||
* Get the system layer of the default display
|
||||
* @return pointer to the sys layer
|
||||
*/
|
||||
lv_obj_t * lv_layer_sys(void);
|
||||
|
||||
/**
|
||||
* Get the bottom layer of the default display
|
||||
* @return pointer to the bottom layer
|
||||
*/
|
||||
lv_obj_t * lv_layer_bottom(void);
|
||||
|
||||
/*---------------------
|
||||
* OTHERS
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Add an event handler to the display
|
||||
* @param disp pointer to a display
|
||||
* @param event_cb an event callback
|
||||
* @param filter event code to react or `LV_EVENT_ALL`
|
||||
* @param user_data optional user_data
|
||||
*/
|
||||
void lv_display_add_event_cb(lv_display_t * disp, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data);
|
||||
|
||||
/**
|
||||
* Get the number of event attached to a display
|
||||
* @param disp pointer to a display
|
||||
* @return number of events
|
||||
*/
|
||||
uint32_t lv_display_get_event_count(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get an event descriptor for an event
|
||||
* @param disp pointer to a display
|
||||
* @param index the index of the event
|
||||
* @return the event descriptor
|
||||
*/
|
||||
lv_event_dsc_t * lv_display_get_event_dsc(lv_display_t * disp, uint32_t index);
|
||||
|
||||
/**
|
||||
* Remove an event
|
||||
* @param disp pointer to a display
|
||||
* @param index the index of the event to remove
|
||||
* @return true: and event was removed; false: no event was removed
|
||||
*/
|
||||
bool lv_display_delete_event(lv_display_t * disp, uint32_t index);
|
||||
|
||||
/**
|
||||
* Remove an event_cb with user_data
|
||||
* @param disp pointer to a display
|
||||
* @param event_cb the event_cb of the event to remove
|
||||
* @param user_data user_data
|
||||
* @return the count of the event removed
|
||||
*/
|
||||
uint32_t lv_display_remove_event_cb_with_user_data(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Send an event to a display
|
||||
* @param disp pointer to a display
|
||||
* @param code an event code. LV_EVENT_...
|
||||
* @param param optional param
|
||||
* @return LV_RESULT_OK: disp wasn't deleted in the event.
|
||||
*/
|
||||
lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, void * param);
|
||||
|
||||
/**
|
||||
* Get the area to be invalidated. Can be used in `LV_EVENT_INVALIDATE_AREA`
|
||||
* @param e pointer to an event
|
||||
* @return the area to invalidated (can be modified as required)
|
||||
*/
|
||||
lv_area_t * lv_event_get_invalidated_area(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the theme of a display. If there are no user created widgets yet the screens' theme will be updated
|
||||
* @param disp pointer to a display
|
||||
* @param th pointer to a theme
|
||||
*/
|
||||
void lv_display_set_theme(lv_display_t * disp, lv_theme_t * th);
|
||||
|
||||
/**
|
||||
* Get the theme of a display
|
||||
* @param disp pointer to a display
|
||||
* @return the display's theme (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_display_get_theme(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get elapsed time since last user activity on a display (e.g. click)
|
||||
* @param disp pointer to a display (NULL to get the overall smallest inactivity)
|
||||
* @return elapsed ticks (milliseconds) since the last activity
|
||||
*/
|
||||
uint32_t lv_display_get_inactive_time(const lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Manually trigger an activity on a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_display_trigger_activity(lv_display_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_display_enable_invalidation(lv_display_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_display_is_invalidation_enabled(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get a pointer to the screen refresher timer to
|
||||
* modify its parameters with `lv_timer_...` functions.
|
||||
* @param disp pointer to a display
|
||||
* @return pointer to the display refresher timer. (NULL on error)
|
||||
*/
|
||||
lv_timer_t * lv_display_get_refr_timer(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Delete screen refresher timer
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_display_delete_refr_timer(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Register vsync event of a display. `LV_EVENT_VSYNC` event will be sent periodically.
|
||||
* Please don't use it in display event listeners, as it may cause memory leaks and illegal access issues.
|
||||
*
|
||||
* @param disp pointer to a display
|
||||
* @param event_cb an event callback
|
||||
* @param user_data optional user_data
|
||||
*/
|
||||
bool lv_display_register_vsync_event(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Unregister vsync event of a display. `LV_EVENT_VSYNC` event won't be sent periodically.
|
||||
* Please don't use it in display event listeners, as it may cause memory leaks and illegal access issues.
|
||||
* @param disp pointer to a display
|
||||
* @param event_cb an event callback
|
||||
* @param user_data optional user_data
|
||||
*/
|
||||
bool lv_display_unregister_vsync_event(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Send an vsync event to a display
|
||||
* @param disp pointer to a display
|
||||
* @param param optional param
|
||||
* @return LV_RESULT_OK: disp wasn't deleted in the event.
|
||||
*/
|
||||
lv_result_t lv_display_send_vsync_event(lv_display_t * disp, void * param);
|
||||
|
||||
void lv_display_set_user_data(lv_display_t * disp, void * user_data);
|
||||
void lv_display_set_driver_data(lv_display_t * disp, void * driver_data);
|
||||
void * lv_display_get_user_data(lv_display_t * disp);
|
||||
void * lv_display_get_driver_data(lv_display_t * disp);
|
||||
lv_draw_buf_t * lv_display_get_buf_active(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Rotate an area in-place according to the display's rotation
|
||||
* @param disp pointer to a display
|
||||
* @param area pointer to an area to rotate
|
||||
*/
|
||||
void lv_display_rotate_area(lv_display_t * disp, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Rotate a point in-place according to the display's rotation
|
||||
* @param disp pointer to a display
|
||||
* @param point pointer to a point to rotate
|
||||
*/
|
||||
void lv_display_rotate_point(lv_display_t * disp, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Get the size of the draw buffers
|
||||
* @param disp pointer to a display
|
||||
* @return the size of the draw buffer in bytes for valid display, 0 otherwise
|
||||
*/
|
||||
uint32_t lv_display_get_draw_buf_size(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Get the size of the invalidated draw buffer. Can be used in the flush callback
|
||||
* to get the number of bytes used in the current render buffer.
|
||||
* @param disp pointer to a display
|
||||
* @param width the width of the invalidated area
|
||||
* @param height the height of the invalidated area
|
||||
* @return the size of the invalidated draw buffer in bytes, not accounting for
|
||||
* any preceding palette information for a valid display, 0 otherwise
|
||||
*/
|
||||
uint32_t lv_display_get_invalidated_draw_buf_size(lv_display_t * disp, uint32_t width, uint32_t height);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/*------------------------------------------------
|
||||
* To improve backward compatibility
|
||||
* Recommended only if you have one display
|
||||
*------------------------------------------------*/
|
||||
|
||||
#ifndef LV_HOR_RES
|
||||
/**
|
||||
* The horizontal resolution of the currently active display.
|
||||
*/
|
||||
#define LV_HOR_RES lv_display_get_horizontal_resolution(lv_display_get_default())
|
||||
#endif
|
||||
|
||||
#ifndef LV_VER_RES
|
||||
/**
|
||||
* The vertical resolution of the currently active display.
|
||||
*/
|
||||
#define LV_VER_RES lv_display_get_vertical_resolution(lv_display_get_default())
|
||||
#endif
|
||||
|
||||
/**
|
||||
* See `lv_dpx()` and `lv_display_dpx()`.
|
||||
* Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP)
|
||||
*
|
||||
* - 40 dip is 40 px on a 160 DPI screen (distance = 1/4 inch).
|
||||
* - 40 dip is 80 px on a 320 DPI screen (distance still = 1/4 inch).
|
||||
*
|
||||
* @sa https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp
|
||||
*/
|
||||
#define LV_DPX_CALC(dpi, n) ((n) == 0 ? 0 :LV_MAX((( (dpi) * (n) + 80) / 160), 1)) /*+80 for rounding*/
|
||||
#define LV_DPX(n) LV_DPX_CALC(lv_display_get_dpi(NULL), n)
|
||||
|
||||
/**
|
||||
* For default display, computes the number of pixels (a distance or size) as if the
|
||||
* display had 160 DPI. This allows you to specify 1/160-th fractions of an inch to
|
||||
* get real distance on the display that will be consistent regardless of its current
|
||||
* DPI. It ensures `lv_dpx(100)`, for example, will have the same physical size
|
||||
* regardless to the DPI of the display.
|
||||
* @param n number of 1/160-th-inch units to compute with
|
||||
* @return number of pixels to use to make that distance
|
||||
*/
|
||||
int32_t lv_dpx(int32_t n);
|
||||
|
||||
/**
|
||||
* For specified display, computes the number of pixels (a distance or size) as if the
|
||||
* display had 160 DPI. This allows you to specify 1/160-th fractions of an inch to
|
||||
* get real distance on the display that will be consistent regardless of its current
|
||||
* DPI. It ensures `lv_dpx(100)`, for example, will have the same physical size
|
||||
* regardless to the DPI of the display.
|
||||
* @param disp pointer to display whose dpi should be considered
|
||||
* @param n number of 1/160-th-inch units to compute with
|
||||
* @return number of pixels to use to make that distance
|
||||
*/
|
||||
int32_t lv_display_dpx(const lv_display_t * disp, int32_t n);
|
||||
|
||||
#if LV_USE_EXT_DATA
|
||||
/**
|
||||
* @brief Attaches external user data and destructor callback to a display
|
||||
*
|
||||
* Associates custom user data with an LVGL display and specifies a destructor function
|
||||
* that will be automatically invoked when the display is deleted to properly clean up
|
||||
* the associated resources.
|
||||
*
|
||||
* @param disp Pointer to a display
|
||||
* @param data User-defined data pointer to associate with the display
|
||||
* @param free_cb Callback function for cleaning up data when display is deleted.
|
||||
* Receives data as parameter. NULL means no cleanup required.
|
||||
*/
|
||||
void lv_display_set_external_data(lv_display_t * disp, void * data, void (* free_cb)(void * data));
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DISPLAY_H*/
|
||||
191
inc/lvgl/src/display/lv_display_private.h
Normal file
191
inc/lvgl/src/display/lv_display_private.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @file lv_display_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DISPLAY_PRIVATE_H
|
||||
#define LV_DISPLAY_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_ext_data.h"
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../core/lv_obj.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "lv_display.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
#include "../debugging/sysmon/lv_sysmon_private.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_INV_BUF_SIZE
|
||||
#define LV_INV_BUF_SIZE 32 /**< Buffer size for invalid areas */
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_display_t {
|
||||
#if LV_USE_EXT_DATA
|
||||
lv_ext_data_t ext_data;
|
||||
#endif
|
||||
/*---------------------
|
||||
* Resolution
|
||||
*--------------------*/
|
||||
|
||||
/** Horizontal resolution.*/
|
||||
int32_t hor_res;
|
||||
|
||||
/** Vertical resolution.*/
|
||||
int32_t ver_res;
|
||||
|
||||
/** Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/
|
||||
int32_t physical_hor_res;
|
||||
|
||||
/** Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/
|
||||
int32_t physical_ver_res;
|
||||
|
||||
/** Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/
|
||||
int32_t offset_x;
|
||||
|
||||
/** Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/
|
||||
int32_t offset_y;
|
||||
|
||||
/** DPI (dot per inch) of the display. Default value is `LV_DPI_DEF`.*/
|
||||
uint32_t dpi;
|
||||
|
||||
/*---------------------
|
||||
* Buffering
|
||||
*--------------------*/
|
||||
lv_draw_buf_t * buf_1;
|
||||
lv_draw_buf_t * buf_2;
|
||||
lv_draw_buf_t * buf_3;
|
||||
|
||||
/** Internal, used by the library*/
|
||||
lv_draw_buf_t * buf_act;
|
||||
|
||||
/** MANDATORY: Write the internal buffer (draw_buf) to the display. 'lv_display_flush_ready()' has to be
|
||||
* called when finished*/
|
||||
lv_display_flush_cb_t flush_cb;
|
||||
|
||||
/**
|
||||
* Used to wait while flushing is ready.
|
||||
* It can do any complex logic to wait, including semaphores, mutexes, polling flags, etc.
|
||||
* If not set `flushing` flag is used which can be cleared with `lv_display_flush_ready()` */
|
||||
lv_display_flush_wait_cb_t flush_wait_cb;
|
||||
|
||||
/** 1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ
|
||||
* Read-Modify-Write issue might occur) */
|
||||
volatile int flushing;
|
||||
|
||||
/** 1: It was the last chunk to flush. (It can't be a bit field because when it's cleared
|
||||
* from IRQ Read-Modify-Write issue might occur) */
|
||||
volatile int flushing_last;
|
||||
volatile uint32_t last_area : 1; /**< 1: last area is being rendered */
|
||||
volatile uint32_t last_part : 1; /**< 1: last part of the current area is being rendered */
|
||||
|
||||
lv_display_render_mode_t render_mode;
|
||||
uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/
|
||||
uint32_t tile_cnt : 8; /**< Divide the display buffer into these number of tiles */
|
||||
uint32_t stride_is_auto : 1; /**< 1: The stride of the buffers was not set explicitly. */
|
||||
|
||||
|
||||
/** 1: The current screen rendering is in progress*/
|
||||
uint32_t rendering_in_progress : 1;
|
||||
|
||||
lv_color_format_t color_format;
|
||||
|
||||
/** Invalidated (marked to redraw) areas*/
|
||||
lv_area_t inv_areas[LV_INV_BUF_SIZE];
|
||||
uint8_t inv_area_joined[LV_INV_BUF_SIZE];
|
||||
uint32_t inv_p;
|
||||
int32_t inv_en_cnt;
|
||||
|
||||
/** Double buffer sync areas (redrawn during last refresh) */
|
||||
lv_ll_t sync_areas;
|
||||
|
||||
lv_draw_buf_t _static_buf1; /**< Used when user pass in a raw buffer as display draw buffer */
|
||||
lv_draw_buf_t _static_buf2;
|
||||
/*---------------------
|
||||
* Layer
|
||||
*--------------------*/
|
||||
lv_layer_t * layer_head;
|
||||
void (*layer_init)(lv_display_t * disp, lv_layer_t * layer);
|
||||
void (*layer_deinit)(lv_display_t * disp, lv_layer_t * layer);
|
||||
|
||||
/*---------------------
|
||||
* Screens
|
||||
*--------------------*/
|
||||
|
||||
/** Screens of the display*/
|
||||
lv_obj_t ** screens; /**< Array of screen objects.*/
|
||||
lv_obj_t * sys_layer; /**< @see lv_display_get_layer_sys*/
|
||||
lv_obj_t * top_layer; /**< @see lv_display_get_layer_top*/
|
||||
lv_obj_t * act_scr; /**< Currently active screen on this display*/
|
||||
lv_obj_t * bottom_layer;/**< @see lv_display_get_layer_bottom*/
|
||||
lv_obj_t * prev_scr; /**< Previous screen. Used during screen animations*/
|
||||
lv_obj_t * scr_to_load; /**< The screen prepared to load in lv_screen_load_anim*/
|
||||
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*/
|
||||
|
||||
/*---------------------
|
||||
* Others
|
||||
*--------------------*/
|
||||
|
||||
void * driver_data; /**< Custom user data*/
|
||||
|
||||
void * user_data; /**< Custom user data*/
|
||||
|
||||
lv_event_list_t event_list;
|
||||
|
||||
uint32_t rotation : 3; /**< Element of lv_display_rotation_t*/
|
||||
|
||||
uint32_t matrix_rotation : 1; /**< 1: Use matrix for display rotation*/
|
||||
|
||||
lv_theme_t * theme; /**< The theme assigned to the screen*/
|
||||
|
||||
/** A timer which periodically checks the dirty areas and refreshes them*/
|
||||
lv_timer_t * refr_timer;
|
||||
|
||||
/*Miscellaneous data*/
|
||||
uint32_t last_activity_time; /**< Last time when there was activity on this display*/
|
||||
|
||||
/** The area being refreshed*/
|
||||
lv_area_t refreshed_area;
|
||||
uint32_t vsync_count;
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
lv_obj_t * perf_label;
|
||||
lv_sysmon_backend_data_t perf_sysmon_backend;
|
||||
lv_sysmon_perf_info_t perf_sysmon_info;
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
lv_obj_t * mem_label;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DISPLAY_PRIVATE_H*/
|
||||
100
inc/lvgl/src/draw/convert/helium/lv_draw_buf_convert_helium.c
Normal file
100
inc/lvgl/src/draw/convert/helium/lv_draw_buf_convert_helium.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert_helium.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM
|
||||
#include "lv_draw_buf_convert_helium.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_indexed_helium(lv_draw_buf_t * buf)
|
||||
{
|
||||
lv_draw_buf_t palette_draw_buf;
|
||||
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
if(!LV_COLOR_FORMAT_IS_INDEXED(buf->header.cf)) {
|
||||
LV_LOG_WARN("Unsupported color format : %d", buf->header.cf);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_memcpy(&palette_draw_buf, buf, sizeof(lv_draw_buf_t));
|
||||
|
||||
palette_draw_buf.header.w = LV_COLOR_INDEXED_PALETTE_SIZE(buf->header.cf);
|
||||
palette_draw_buf.header.h = 1;
|
||||
palette_draw_buf.header.cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
palette_draw_buf.header.stride = 4 * palette_draw_buf.header.w;
|
||||
|
||||
return _lv_draw_buf_convert_premultiply_argb8888_helium(&palette_draw_buf);
|
||||
}
|
||||
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_argb8888_helium(lv_draw_buf_t * buf)
|
||||
{
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
uint32_t h = buf->header.h;
|
||||
uint32_t w = buf->header.w;
|
||||
uint32_t stride = buf->header.stride;
|
||||
uint8_t * data = (uint8_t *)buf->data;
|
||||
|
||||
if(buf->header.cf != LV_COLOR_FORMAT_ARGB8888) {
|
||||
LV_LOG_WARN("Unsupported color format : %d", buf->header.cf);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
__asm volatile(
|
||||
" .p2align 2 \n"
|
||||
" 1: \n"
|
||||
" mov r0, %[pSource] \n"
|
||||
" mov r1, %[pTarget] \n"
|
||||
" wlstp.8 lr, %[w], 3f \n"
|
||||
" 2: \n"
|
||||
" vld40.u8 {q0, q1, q2, q3}, [r0] \n"
|
||||
" vld41.u8 {q0, q1, q2, q3}, [r0] \n"
|
||||
" vld42.u8 {q0, q1, q2, q3}, [r0] \n"
|
||||
" vld43.u8 {q0, q1, q2, q3}, [r0]! \n"
|
||||
" vrmulh.u8 q0, q0, q3 \n"
|
||||
" vrmulh.u8 q1, q1, q3 \n"
|
||||
" vrmulh.u8 q2, q2, q3 \n"
|
||||
" vst40.u8 {q0, q1, q2, q3}, [r1] \n"
|
||||
" vst41.u8 {q0, q1, q2, q3}, [r1] \n"
|
||||
" vst42.u8 {q0, q1, q2, q3}, [r1] \n"
|
||||
" vst43.u8 {q0, q1, q2, q3}, [r1]! \n"
|
||||
" letp lr, 2b \n"
|
||||
" 3: \n"
|
||||
" adds %[pSource], %[src_stride] \n"
|
||||
" adds %[pTarget], %[dst_stride] \n"
|
||||
" subs %[h], #1 \n"
|
||||
" bne 1b \n"
|
||||
: [pSource] "+r"(data), [pTarget] "+r"(data), [h] "+r"(h)
|
||||
: [w] "r"(w), [src_stride] "r"(stride), [dst_stride] "r"(stride)
|
||||
: "q0", "q1", "q2", "q3", "r0", "r1", "lr", "memory");
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
#endif /* LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM */
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert_helium.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_BUF_CONVERT_HELIUM_H
|
||||
#define LV_DRAW_BUF_CONVERT_HELIUM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../../misc/lv_color.h"
|
||||
#include "../../lv_draw_buf.h"
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_INDEXED
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_INDEXED(buf) \
|
||||
_lv_draw_buf_convert_premultiply_indexed_helium(buf)
|
||||
#endif
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888(buf) \
|
||||
_lv_draw_buf_convert_premultiply_argb8888_helium(buf)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert indexed draw_buf to premultiplied format with helium specific optimizations
|
||||
* @param buf pointer to a draw buf
|
||||
*/
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_indexed_helium(lv_draw_buf_t * buf);
|
||||
|
||||
/**
|
||||
* Convert argb8888 draw_buf to premultiplied format with helium specific optimizations
|
||||
* @param buf pointer to a draw buf
|
||||
*/
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_argb8888_helium(lv_draw_buf_t * buf);
|
||||
|
||||
#endif /*LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM*/
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_BUF_CONVERT_HELIUM_H */
|
||||
132
inc/lvgl/src/draw/convert/lv_draw_buf_convert.c
Normal file
132
inc/lvgl/src/draw/convert/lv_draw_buf_convert.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_buf_convert.h"
|
||||
#include "../../misc/lv_profiler.h"
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON
|
||||
#include "neon/lv_draw_buf_convert_neon.h"
|
||||
#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM
|
||||
#include "helium/lv_draw_buf_convert_helium.h"
|
||||
#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM
|
||||
#include LV_DRAW_SW_ASM_CUSTOM_INCLUDE
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_INDEXED
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_INDEXED(...) LV_RESULT_INVALID
|
||||
#endif
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888(...) LV_RESULT_INVALID
|
||||
#endif
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_RGB565A8
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_RGB565A8(...) LV_RESULT_INVALID
|
||||
#endif
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_ARGB8565
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_ARGB8565(...) LV_RESULT_INVALID
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_result_t lv_draw_buf_convert_premultiply(lv_draw_buf_t * draw_buf)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
LV_ASSERT_NULL(draw_buf);
|
||||
|
||||
/*Premultiply color with alpha, do case by case by judging color format*/
|
||||
lv_color_format_t cf = draw_buf->header.cf;
|
||||
if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
|
||||
if(LV_RESULT_INVALID == LV_DRAW_CONVERT_PREMULTIPLY_INDEXED(draw_buf)) {
|
||||
int size = LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||
lv_color32_t * palette = (lv_color32_t *)draw_buf->data;
|
||||
for(int i = 0; i < size; i++) {
|
||||
lv_color_premultiply(&palette[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cf == LV_COLOR_FORMAT_ARGB8888) {
|
||||
if(LV_RESULT_INVALID == LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888(draw_buf)) {
|
||||
uint32_t h = draw_buf->header.h;
|
||||
uint32_t w = draw_buf->header.w;
|
||||
uint32_t stride = draw_buf->header.stride;
|
||||
uint8_t * line = (uint8_t *)draw_buf->data;
|
||||
for(uint32_t y = 0; y < h; y++) {
|
||||
lv_color32_t * pixel = (lv_color32_t *)line;
|
||||
for(uint32_t x = 0; x < w; x++) {
|
||||
lv_color_premultiply(pixel);
|
||||
pixel++;
|
||||
}
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cf == LV_COLOR_FORMAT_RGB565A8) {
|
||||
if(LV_RESULT_INVALID == LV_DRAW_CONVERT_PREMULTIPLY_RGB565A8(draw_buf)) {
|
||||
uint32_t h = draw_buf->header.h;
|
||||
uint32_t w = draw_buf->header.w;
|
||||
uint32_t stride = draw_buf->header.stride;
|
||||
uint32_t alpha_stride = stride / 2;
|
||||
uint8_t * line = (uint8_t *)draw_buf->data;
|
||||
lv_opa_t * alpha = (lv_opa_t *)(line + stride * h);
|
||||
for(uint32_t y = 0; y < h; y++) {
|
||||
lv_color16_t * pixel = (lv_color16_t *)line;
|
||||
for(uint32_t x = 0; x < w; x++) {
|
||||
lv_color16_premultiply(pixel, alpha[x]);
|
||||
pixel++;
|
||||
}
|
||||
line += stride;
|
||||
alpha += alpha_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cf == LV_COLOR_FORMAT_ARGB8565) {
|
||||
if(LV_RESULT_INVALID == LV_DRAW_CONVERT_PREMULTIPLY_ARGB8565(draw_buf)) {
|
||||
uint32_t h = draw_buf->header.h;
|
||||
uint32_t w = draw_buf->header.w;
|
||||
uint32_t stride = draw_buf->header.stride;
|
||||
uint8_t * line = (uint8_t *)draw_buf->data;
|
||||
for(uint32_t y = 0; y < h; y++) {
|
||||
uint8_t * pixel = line;
|
||||
for(uint32_t x = 0; x < w; x++) {
|
||||
uint8_t alpha = pixel[2];
|
||||
lv_color16_premultiply((lv_color16_t *)pixel, alpha);
|
||||
pixel += 3;
|
||||
}
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("color format: %d not supported for premultiply", cf);
|
||||
LV_PROFILER_DRAW_END;
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
39
inc/lvgl/src/draw/convert/lv_draw_buf_convert.h
Normal file
39
inc/lvgl/src/draw/convert/lv_draw_buf_convert.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_BUF_CONVERT_H
|
||||
#define LV_DRAW_BUF_CONVERT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../lv_draw_buf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert draw_buf to premultiplied format
|
||||
* @param buf pointer to a draw buf
|
||||
*/
|
||||
lv_result_t lv_draw_buf_convert_premultiply(lv_draw_buf_t * buf);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_BUF_CONVERT_H */
|
||||
132
inc/lvgl/src/draw/convert/neon/lv_draw_buf_convert_neon.c
Normal file
132
inc/lvgl/src/draw/convert/neon/lv_draw_buf_convert_neon.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert_neon.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include "lv_draw_buf_convert_neon.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_indexed_neon(lv_draw_buf_t * buf)
|
||||
{
|
||||
lv_draw_buf_t palette_draw_buf;
|
||||
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
if(!LV_COLOR_FORMAT_IS_INDEXED(buf->header.cf)) {
|
||||
LV_LOG_WARN("Unsupported color format : %d", buf->header.cf);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_memcpy(&palette_draw_buf, buf, sizeof(lv_draw_buf_t));
|
||||
|
||||
palette_draw_buf.header.w = LV_COLOR_INDEXED_PALETTE_SIZE(buf->header.cf);
|
||||
palette_draw_buf.header.h = 1;
|
||||
palette_draw_buf.header.cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
palette_draw_buf.header.stride = 4 * palette_draw_buf.header.w;
|
||||
|
||||
return _lv_draw_buf_convert_premultiply_argb8888_neon(&palette_draw_buf);
|
||||
|
||||
}
|
||||
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_argb8888_neon(lv_draw_buf_t * buf)
|
||||
{
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
uint32_t h = buf->header.h;
|
||||
uint32_t w = buf->header.w;
|
||||
uint32_t stride = buf->header.stride;
|
||||
uint8_t * data = (uint8_t *)buf->data;
|
||||
|
||||
if(buf->header.cf != LV_COLOR_FORMAT_ARGB8888) {
|
||||
LV_LOG_WARN("Unsupported color format : %d", buf->header.cf);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
for(uint32_t y = 0; y < h; y++) {
|
||||
uint8_t * p = (uint8_t *)data;
|
||||
uint32_t remaining_pixels = w;
|
||||
|
||||
while(remaining_pixels >= 8) {
|
||||
uint8x8x4_t rgba = vld4_u8(p);
|
||||
|
||||
uint16x8_t r16 = vmovl_u8(rgba.val[0]);
|
||||
uint16x8_t g16 = vmovl_u8(rgba.val[1]);
|
||||
uint16x8_t b16 = vmovl_u8(rgba.val[2]);
|
||||
uint16x8_t a16 = vmovl_u8(rgba.val[3]);
|
||||
|
||||
rgba.val[0] = vshrn_n_u16(vmulq_u16(r16, a16), 8);
|
||||
rgba.val[1] = vshrn_n_u16(vmulq_u16(g16, a16), 8);
|
||||
rgba.val[2] = vshrn_n_u16(vmulq_u16(b16, a16), 8);
|
||||
|
||||
vst4_u8(p, rgba);
|
||||
|
||||
p += 8 * 4;
|
||||
remaining_pixels -= 8;
|
||||
}
|
||||
|
||||
if(remaining_pixels >= 4) {
|
||||
uint8x8x4_t rgba;
|
||||
rgba = vld4_lane_u8(p, rgba, 0);
|
||||
rgba = vld4_lane_u8(p + 4, rgba, 1);
|
||||
rgba = vld4_lane_u8(p + 8, rgba, 2);
|
||||
rgba = vld4_lane_u8(p + 12, rgba, 3);
|
||||
|
||||
uint16x8_t r16 = vmovl_u8(rgba.val[0]);
|
||||
uint16x8_t g16 = vmovl_u8(rgba.val[1]);
|
||||
uint16x8_t b16 = vmovl_u8(rgba.val[2]);
|
||||
uint16x8_t a16 = vmovl_u8(rgba.val[3]);
|
||||
|
||||
rgba.val[0] = vshrn_n_u16(vmulq_u16(r16, a16), 8);
|
||||
rgba.val[1] = vshrn_n_u16(vmulq_u16(g16, a16), 8);
|
||||
rgba.val[2] = vshrn_n_u16(vmulq_u16(b16, a16), 8);
|
||||
|
||||
vst4_lane_u8(p, rgba, 0);
|
||||
vst4_lane_u8(p + 4, rgba, 1);
|
||||
vst4_lane_u8(p + 8, rgba, 2);
|
||||
vst4_lane_u8(p + 12, rgba, 3);
|
||||
|
||||
p += 4 * 4;
|
||||
remaining_pixels -= 4;
|
||||
}
|
||||
|
||||
while(remaining_pixels--) {
|
||||
uint8_t a = p[3];
|
||||
p[0] = ((uint16_t)(p[0]) * a) >> 8;
|
||||
p[1] = ((uint16_t)(p[1]) * a) >> 8;
|
||||
p[2] = ((uint16_t)(p[2]) * a) >> 8;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
}
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
#endif /* LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON */
|
||||
58
inc/lvgl/src/draw/convert/neon/lv_draw_buf_convert_neon.h
Normal file
58
inc/lvgl/src/draw/convert/neon/lv_draw_buf_convert_neon.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @file lv_draw_buf_convert_neon.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_BUF_CONVERT_NEON_H
|
||||
#define LV_DRAW_BUF_CONVERT_NEON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../../misc/lv_color.h"
|
||||
#include "../../lv_draw_buf.h"
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_INDEXED
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_INDEXED(buf) \
|
||||
_lv_draw_buf_convert_premultiply_indexed_neon(buf)
|
||||
#endif
|
||||
|
||||
#ifndef LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888
|
||||
#define LV_DRAW_CONVERT_PREMULTIPLY_ARGB8888(buf) \
|
||||
_lv_draw_buf_convert_premultiply_argb8888_neon(buf)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert indexed draw_buf to premultiplied format with neon specific optimizations
|
||||
* @param buf pointer to a draw buf
|
||||
*/
|
||||
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_indexed_neon(lv_draw_buf_t * buf);
|
||||
|
||||
/**
|
||||
* Convert argb8888 draw_buf to premultiplied format with neon specific optimizations
|
||||
* @param buf pointer to a draw buf
|
||||
*/
|
||||
lv_result_t _lv_draw_buf_convert_premultiply_argb8888_neon(lv_draw_buf_t * buf);
|
||||
#endif /*LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_BUF_CONVERT_NEON_H */
|
||||
396
inc/lvgl/src/draw/dma2d/lv_draw_dma2d.c
Normal file
396
inc/lvgl/src/draw/dma2d/lv_draw_dma2d.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/**
|
||||
* @file lv_draw_dma2d.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_dma2d_private.h"
|
||||
#if LV_USE_DRAW_DMA2D
|
||||
|
||||
#include "../sw/lv_draw_sw.h"
|
||||
#include "../../misc/lv_area_private.h"
|
||||
|
||||
#if !LV_DRAW_DMA2D_ASYNC && LV_USE_DRAW_DMA2D_INTERRUPT
|
||||
#warning LV_USE_DRAW_DMA2D_INTERRUPT is 1 but has no effect because LV_USE_OS is LV_OS_NONE
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_DMA2D 5
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static int32_t evaluate_cb(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
static int32_t dispatch_cb(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
static int32_t delete_cb(lv_draw_unit_t * draw_unit);
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
static int32_t wait_finish_cb(lv_draw_unit_t * u);
|
||||
#endif
|
||||
#if !LV_DRAW_DMA2D_ASYNC
|
||||
static bool check_transfer_completion(void);
|
||||
#endif
|
||||
static void post_transfer_tasks(lv_draw_dma2d_unit_t * u);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
static lv_draw_dma2d_unit_t * g_unit;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_dma2d_init(void)
|
||||
{
|
||||
lv_draw_dma2d_unit_t * draw_dma2d_unit = lv_draw_create_unit(sizeof(lv_draw_dma2d_unit_t));
|
||||
draw_dma2d_unit->base_unit.evaluate_cb = evaluate_cb;
|
||||
draw_dma2d_unit->base_unit.dispatch_cb = dispatch_cb;
|
||||
draw_dma2d_unit->base_unit.delete_cb = delete_cb;
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
draw_dma2d_unit->base_unit.wait_for_finish_cb = wait_finish_cb;
|
||||
#endif
|
||||
draw_dma2d_unit->base_unit.name = "DMA2D";
|
||||
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
g_unit = draw_dma2d_unit;
|
||||
lv_thread_sync_init(&draw_dma2d_unit->interrupt_signal);
|
||||
#endif
|
||||
|
||||
/* enable the DMA2D clock */
|
||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32U5) || defined(STM32L4)
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
|
||||
#elif defined(STM32H7)
|
||||
RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN;
|
||||
#elif defined(STM32H7RS) || defined(STM32N6)
|
||||
RCC->AHB5ENR |= RCC_AHB5ENR_DMA2DEN;
|
||||
#else
|
||||
#warning "LVGL can't enable the clock for DMA2D"
|
||||
#endif
|
||||
|
||||
/* disable dead time */
|
||||
DMA2D->AMTCR = 0;
|
||||
|
||||
/* enable the interrupt */
|
||||
NVIC_EnableIRQ(DMA2D_IRQn);
|
||||
}
|
||||
|
||||
void lv_draw_dma2d_deinit(void)
|
||||
{
|
||||
/* disable the interrupt */
|
||||
NVIC_DisableIRQ(DMA2D_IRQn);
|
||||
|
||||
/* disable the DMA2D clock */
|
||||
#if defined(STM32F4) || defined(STM32F7) || defined(STM32U5) || defined(STM32L4)
|
||||
RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2DEN;
|
||||
#elif defined(STM32H7)
|
||||
RCC->AHB3ENR &= ~RCC_AHB3ENR_DMA2DEN;
|
||||
#elif defined(STM32H7RS) || defined(STM32N6)
|
||||
RCC->AHB5ENR &= ~RCC_AHB5ENR_DMA2DEN;
|
||||
#endif
|
||||
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
lv_result_t res = lv_thread_sync_delete(&g_unit->interrupt_signal);
|
||||
LV_ASSERT(res == LV_RESULT_OK);
|
||||
|
||||
g_unit = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_USE_DRAW_DMA2D_INTERRUPT
|
||||
void lv_draw_dma2d_transfer_complete_interrupt_handler(void)
|
||||
{
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
lv_thread_sync_signal_isr(&g_unit->interrupt_signal);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_draw_dma2d_output_cf_t lv_draw_dma2d_cf_to_dma2d_output_cf(lv_color_format_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
return LV_DRAW_DMA2D_OUTPUT_CF_ARGB8888;
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
return LV_DRAW_DMA2D_OUTPUT_CF_RGB888;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
return LV_DRAW_DMA2D_OUTPUT_CF_RGB565;
|
||||
case LV_COLOR_FORMAT_ARGB1555:
|
||||
return LV_DRAW_DMA2D_OUTPUT_CF_ARGB1555;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "unsupported output color format");
|
||||
}
|
||||
return LV_DRAW_DMA2D_OUTPUT_CF_RGB565;
|
||||
}
|
||||
|
||||
uint32_t lv_draw_dma2d_color_to_dma2d_color(lv_draw_dma2d_output_cf_t cf, lv_color_t color)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_DRAW_DMA2D_OUTPUT_CF_ARGB8888:
|
||||
case LV_DRAW_DMA2D_OUTPUT_CF_RGB888:
|
||||
return lv_color_to_u32(color);
|
||||
case LV_DRAW_DMA2D_OUTPUT_CF_RGB565:
|
||||
return lv_color_to_u16(color);
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "unsupported output color format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lv_draw_dma2d_configure_and_start_transfer(const lv_draw_dma2d_configuration_t * conf)
|
||||
{
|
||||
/* number of lines register */
|
||||
DMA2D->NLR = (conf->w << DMA2D_NLR_PL_Pos) | (conf->h << DMA2D_NLR_NL_Pos);
|
||||
|
||||
/* output */
|
||||
|
||||
/* output memory address register */
|
||||
DMA2D->OMAR = (uint32_t)(uintptr_t) conf->output_address;
|
||||
/* output offset register */
|
||||
DMA2D->OOR = conf->output_offset;
|
||||
/* output pixel format converter control register */
|
||||
DMA2D->OPFCCR = ((uint32_t) conf->output_cf) << DMA2D_OPFCCR_CM_Pos;
|
||||
|
||||
/* Fill color. Only for mode LV_DRAW_DMA2D_MODE_REGISTER_TO_MEMORY */
|
||||
DMA2D->OCOLR = conf->reg_to_mem_mode_color;
|
||||
|
||||
/* foreground */
|
||||
|
||||
/* foreground memory address register */
|
||||
DMA2D->FGMAR = (uint32_t)(uintptr_t) conf->fg_address;
|
||||
/* foreground offset register */
|
||||
DMA2D->FGOR = conf->fg_offset;
|
||||
/* foreground color. only for mem-to-mem with blending and fixed-color foreground */
|
||||
DMA2D->FGCOLR = conf->fg_color;
|
||||
/* foreground pixel format converter control register */
|
||||
DMA2D->FGPFCCR = (((uint32_t) conf->fg_cf) << DMA2D_FGPFCCR_CM_Pos)
|
||||
| (conf->fg_alpha << DMA2D_FGPFCCR_ALPHA_Pos)
|
||||
| (conf->fg_alpha_mode << DMA2D_FGPFCCR_AM_Pos);
|
||||
|
||||
/* background */
|
||||
|
||||
DMA2D->BGMAR = (uint32_t)(uintptr_t) conf->bg_address;
|
||||
DMA2D->BGOR = conf->bg_offset;
|
||||
DMA2D->BGCOLR = conf->bg_color;
|
||||
DMA2D->BGPFCCR = (((uint32_t) conf->bg_cf) << DMA2D_BGPFCCR_CM_Pos)
|
||||
| (conf->bg_alpha << DMA2D_BGPFCCR_ALPHA_Pos)
|
||||
| (conf->bg_alpha_mode << DMA2D_BGPFCCR_AM_Pos);
|
||||
|
||||
/* ensure the DMA2D register values are observed before the start transfer bit is set */
|
||||
__DSB();
|
||||
|
||||
/* start the transfer (also set mode and enable transfer complete interrupt) */
|
||||
DMA2D->CR = DMA2D_CR_START | (((uint32_t) conf->mode) << DMA2D_CR_MODE_Pos)
|
||||
#if LV_USE_DRAW_DMA2D_INTERRUPT
|
||||
| DMA2D_CR_TCIE
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
void lv_draw_dma2d_invalidate_cache(const lv_draw_dma2d_cache_area_t * mem_area)
|
||||
{
|
||||
if(SCB->CCR & SCB_CCR_DC_Msk) {
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)mem_area->first_byte,
|
||||
mem_area->stride * mem_area->height);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_draw_dma2d_clean_cache(const lv_draw_dma2d_cache_area_t * mem_area)
|
||||
{
|
||||
if(SCB->CCR & SCB_CCR_DC_Msk) {
|
||||
SCB_CleanDCache_by_Addr((uint32_t *)mem_area->first_byte,
|
||||
mem_area->stride * mem_area->height);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static int32_t evaluate_cb(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
|
||||
{
|
||||
switch(task->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL: {
|
||||
lv_draw_fill_dsc_t * dsc = task->draw_dsc;
|
||||
if(!(dsc->radius == 0
|
||||
&& dsc->grad.dir == LV_GRAD_DIR_NONE
|
||||
&& (dsc->base.layer->color_format == LV_COLOR_FORMAT_ARGB8888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_XRGB8888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB565))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE: {
|
||||
lv_draw_image_dsc_t * dsc = task->draw_dsc;
|
||||
if(!(dsc->header.cf < LV_COLOR_FORMAT_PROPRIETARY_START
|
||||
&& dsc->clip_radius == 0
|
||||
&& dsc->bitmap_mask_src == NULL
|
||||
&& dsc->sup == NULL
|
||||
&& dsc->tile == 0
|
||||
&& dsc->blend_mode == LV_BLEND_MODE_NORMAL
|
||||
&& dsc->recolor_opa <= LV_OPA_MIN
|
||||
&& dsc->skew_y == 0
|
||||
&& dsc->skew_x == 0
|
||||
&& dsc->scale_x == 256
|
||||
&& dsc->scale_y == 256
|
||||
&& dsc->rotation == 0
|
||||
&& lv_image_src_get_type(dsc->src) == LV_IMAGE_SRC_VARIABLE
|
||||
&& (dsc->header.cf == LV_COLOR_FORMAT_ARGB8888
|
||||
|| dsc->header.cf == LV_COLOR_FORMAT_XRGB8888
|
||||
|| dsc->header.cf == LV_COLOR_FORMAT_RGB888
|
||||
|| dsc->header.cf == LV_COLOR_FORMAT_RGB565
|
||||
|| dsc->header.cf == LV_COLOR_FORMAT_ARGB1555)
|
||||
&& (dsc->base.layer->color_format == LV_COLOR_FORMAT_ARGB8888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_XRGB8888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB565))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
task->preferred_draw_unit_id = DRAW_UNIT_ID_DMA2D;
|
||||
task->preference_score = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t dispatch_cb(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_dma2d_unit_t * draw_dma2d_unit = (lv_draw_dma2d_unit_t *) draw_unit;
|
||||
|
||||
if(draw_dma2d_unit->task_act) {
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
/*Return immediately if it's busy with draw task*/
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
#else
|
||||
if(!check_transfer_completion()) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
post_transfer_tasks(draw_dma2d_unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_DMA2D);
|
||||
if(t == NULL) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||
if(buf == NULL) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
t->draw_unit = draw_unit;
|
||||
draw_dma2d_unit->task_act = t;
|
||||
|
||||
if(t->type == LV_DRAW_TASK_TYPE_FILL) {
|
||||
lv_draw_fill_dsc_t * dsc = t->draw_dsc;
|
||||
const lv_area_t * coords = &t->area;
|
||||
lv_area_t clipped_coords;
|
||||
if(!lv_area_intersect(&clipped_coords, coords, &t->clip_area)) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
void * dest = lv_draw_layer_go_to_xy(layer,
|
||||
clipped_coords.x1 - layer->buf_area.x1,
|
||||
clipped_coords.y1 - layer->buf_area.y1);
|
||||
|
||||
if(dsc->opa >= LV_OPA_MAX) {
|
||||
lv_draw_dma2d_opaque_fill(t,
|
||||
dest,
|
||||
lv_area_get_width(&clipped_coords),
|
||||
lv_area_get_height(&clipped_coords),
|
||||
lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), dsc->base.layer->color_format));
|
||||
}
|
||||
else {
|
||||
lv_draw_dma2d_fill(t,
|
||||
dest,
|
||||
lv_area_get_width(&clipped_coords),
|
||||
lv_area_get_height(&clipped_coords),
|
||||
lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), dsc->base.layer->color_format));
|
||||
}
|
||||
}
|
||||
else if(t->type == LV_DRAW_TASK_TYPE_IMAGE) {
|
||||
lv_draw_image_dsc_t * dsc = t->draw_dsc;
|
||||
const lv_area_t * coords = &t->area;
|
||||
lv_area_t clipped_coords;
|
||||
if(!lv_area_intersect(&clipped_coords, coords, &t->clip_area)) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
if(dsc->opa >= LV_OPA_MAX) {
|
||||
lv_draw_dma2d_opaque_image(t, dsc, &t->area);
|
||||
}
|
||||
else {
|
||||
lv_draw_dma2d_image(t, dsc, &t->area);
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_dispatch_request();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t delete_cb(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
static int32_t wait_finish_cb(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
lv_draw_dma2d_unit_t * u = (lv_draw_dma2d_unit_t *) draw_unit;
|
||||
|
||||
/* If a DMA2D task has been dispatched, wait its interrupt */
|
||||
lv_thread_sync_wait(&u->interrupt_signal);
|
||||
|
||||
/* Then cleanup the DMA2D draw unit to accept a new task */
|
||||
post_transfer_tasks(u);
|
||||
return 0;
|
||||
}
|
||||
#endif /*LV_DRAW_DMA2D_ASYNC*/
|
||||
|
||||
#if !LV_DRAW_DMA2D_ASYNC
|
||||
static bool check_transfer_completion(void)
|
||||
{
|
||||
return !(DMA2D->CR & DMA2D_CR_START);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void post_transfer_tasks(lv_draw_dma2d_unit_t * u)
|
||||
{
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_invalidate_cache(&u->writing_area);
|
||||
#endif
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_FINISHED;
|
||||
u->task_act = NULL;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_DMA2D*/
|
||||
49
inc/lvgl/src/draw/dma2d/lv_draw_dma2d.h
Normal file
49
inc/lvgl/src/draw/dma2d/lv_draw_dma2d.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file lv_draw_dma2d.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_DMA2D_H
|
||||
#define LV_DRAW_DMA2D_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_DRAW_DMA2D
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_dma2d_init(void);
|
||||
void lv_draw_dma2d_deinit(void);
|
||||
|
||||
#if LV_USE_DRAW_DMA2D_INTERRUPT
|
||||
void lv_draw_dma2d_transfer_complete_interrupt_handler(void);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_DMA2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_DMA2D_H*/
|
||||
133
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_fill.c
Normal file
133
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_fill.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file lv_draw_dma2d_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_dma2d_private.h"
|
||||
#if LV_USE_DRAW_DMA2D
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_dma2d_opaque_fill(lv_draw_task_t * t, void * first_pixel, int32_t w, int32_t h, int32_t stride)
|
||||
{
|
||||
lv_draw_fill_dsc_t * dsc = t->draw_dsc;
|
||||
lv_color_format_t cf = dsc->base.layer->color_format;
|
||||
|
||||
lv_draw_dma2d_output_cf_t output_cf = lv_draw_dma2d_cf_to_dma2d_output_cf(cf);
|
||||
uint32_t cf_size = LV_COLOR_FORMAT_GET_SIZE(cf);
|
||||
uint32_t reg_to_mem_color = lv_draw_dma2d_color_to_dma2d_color(output_cf, dsc->color);
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t cache_area = {
|
||||
.first_byte = first_pixel,
|
||||
.width_bytes = w * cf_size,
|
||||
.height = h,
|
||||
.stride = stride
|
||||
};
|
||||
lv_draw_dma2d_unit_t * u = (lv_draw_dma2d_unit_t *) t->draw_unit;
|
||||
lv_memcpy(&u->writing_area, &cache_area, sizeof(lv_draw_dma2d_cache_area_t));
|
||||
#endif
|
||||
|
||||
lv_draw_dma2d_configuration_t conf = {
|
||||
.mode = LV_DRAW_DMA2D_MODE_REGISTER_TO_MEMORY,
|
||||
.w = w,
|
||||
.h = h,
|
||||
|
||||
.output_address = first_pixel,
|
||||
.output_offset = (stride / cf_size) - w,
|
||||
.output_cf = output_cf,
|
||||
|
||||
.reg_to_mem_mode_color = reg_to_mem_color
|
||||
};
|
||||
lv_draw_dma2d_configure_and_start_transfer(&conf);
|
||||
}
|
||||
|
||||
void lv_draw_dma2d_fill(lv_draw_task_t * t, void * first_pixel, int32_t w, int32_t h, int32_t stride)
|
||||
{
|
||||
lv_draw_fill_dsc_t * dsc = t->draw_dsc;
|
||||
lv_color_t color = dsc->color;
|
||||
lv_color_format_t cf = dsc->base.layer->color_format;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
|
||||
lv_draw_dma2d_output_cf_t output_cf = lv_draw_dma2d_cf_to_dma2d_output_cf(cf);
|
||||
uint32_t cf_size = LV_COLOR_FORMAT_GET_SIZE(cf);
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t cache_area = {
|
||||
.first_byte = first_pixel,
|
||||
.width_bytes = w * cf_size,
|
||||
.height = h,
|
||||
.stride = stride
|
||||
};
|
||||
lv_draw_dma2d_unit_t * u = (lv_draw_dma2d_unit_t *) t->draw_unit;
|
||||
lv_memcpy(&u->writing_area, &cache_area, sizeof(lv_draw_dma2d_cache_area_t));
|
||||
|
||||
/* make sure the background area DMA2D is blending is up-to-date in main memory */
|
||||
lv_draw_dma2d_clean_cache(&cache_area);
|
||||
#endif
|
||||
|
||||
uint32_t output_offset = (stride / cf_size) - w;
|
||||
|
||||
lv_draw_dma2d_configuration_t conf = {
|
||||
.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING,
|
||||
.w = w,
|
||||
.h = h,
|
||||
|
||||
.output_address = first_pixel,
|
||||
.output_offset = output_offset,
|
||||
.output_cf = output_cf,
|
||||
|
||||
.fg_color = lv_color_to_u32(color),
|
||||
.fg_address = first_pixel,
|
||||
.fg_offset = output_offset,
|
||||
.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL,
|
||||
.fg_alpha = opa,
|
||||
.fg_cf = LV_DRAW_DMA2D_FGBG_CF_A8,
|
||||
|
||||
.bg_address = first_pixel,
|
||||
.bg_offset = output_offset,
|
||||
.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_NO_MODIFY_IMAGE_ALPHA_CHANNEL,
|
||||
.bg_alpha = opa,
|
||||
.bg_cf = (lv_draw_dma2d_fgbg_cf_t) output_cf
|
||||
};
|
||||
|
||||
/* Background alpha channel should be treated as 0xFF if the cf is XRGB */
|
||||
if(cf == LV_COLOR_FORMAT_XRGB8888) {
|
||||
conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
|
||||
conf.bg_alpha = 0xff;
|
||||
}
|
||||
|
||||
lv_draw_dma2d_configure_and_start_transfer(&conf);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_DMA2D*/
|
||||
262
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_img.c
Normal file
262
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_img.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* @file lv_draw_dma2d_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_dma2d_private.h"
|
||||
#if LV_USE_DRAW_DMA2D
|
||||
|
||||
#include "../lv_draw_image_private.h"
|
||||
#include "../lv_image_decoder_private.h"
|
||||
#include "../../misc/lv_area_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_draw_dma2d_opaque_image_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area);
|
||||
|
||||
static void lv_draw_dma2d_image_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_dma2d_opaque_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(!draw_dsc->tile) {
|
||||
lv_draw_image_normal_helper(t, draw_dsc, coords, lv_draw_dma2d_opaque_image_core, NULL);
|
||||
}
|
||||
else {
|
||||
lv_draw_image_tiled_helper(t, draw_dsc, coords, lv_draw_dma2d_opaque_image_core, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_draw_dma2d_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(!draw_dsc->tile) {
|
||||
lv_draw_image_normal_helper(t, draw_dsc, coords, lv_draw_dma2d_image_core, NULL);
|
||||
}
|
||||
else {
|
||||
lv_draw_image_tiled_helper(t, draw_dsc, coords, lv_draw_dma2d_image_core, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_draw_dma2d_opaque_image_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area)
|
||||
{
|
||||
LV_UNUSED(sup);
|
||||
LV_UNUSED(img_coords);
|
||||
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
|
||||
void * dest_first_pixel = lv_draw_layer_go_to_xy(layer,
|
||||
clipped_img_area->x1 - layer->buf_area.x1,
|
||||
clipped_img_area->y1 - layer->buf_area.y1);
|
||||
int32_t dest_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format);
|
||||
|
||||
int32_t w = lv_area_get_width(clipped_img_area);
|
||||
int32_t h = lv_area_get_height(clipped_img_area);
|
||||
|
||||
lv_color_format_t output_cf = layer->color_format;
|
||||
uint32_t output_cf_size = lv_color_format_get_size(output_cf);
|
||||
lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf);
|
||||
|
||||
const lv_draw_buf_t * decoded = decoder_dsc->decoded;
|
||||
const uint8_t * src_buf = decoded->data;
|
||||
uint32_t image_stride = decoded->header.stride;
|
||||
lv_color_format_t image_cf = decoded->header.cf;
|
||||
lv_draw_dma2d_fgbg_cf_t image_cf_dma2d = (lv_draw_dma2d_fgbg_cf_t) lv_draw_dma2d_cf_to_dma2d_output_cf(image_cf);
|
||||
uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf);
|
||||
if(image_stride == 0) image_stride = image_cf_size * decoded->header.w;
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t dest_area = {
|
||||
.first_byte = dest_first_pixel,
|
||||
.width_bytes = w * output_cf_size,
|
||||
.height = h,
|
||||
.stride = dest_stride
|
||||
};
|
||||
lv_draw_dma2d_unit_t * u = (lv_draw_dma2d_unit_t *) t->draw_unit;
|
||||
lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t));
|
||||
if(lv_color_format_has_alpha(image_cf)) {
|
||||
/* make sure the background area DMA2D is blending is up-to-date in main memory */
|
||||
lv_draw_dma2d_clean_cache(&dest_area);
|
||||
}
|
||||
#endif
|
||||
|
||||
const void * image_first_byte = src_buf
|
||||
+ (image_stride * (clipped_img_area->y1 - draw_dsc->image_area.y1))
|
||||
+ (image_cf_size * (clipped_img_area->x1 - draw_dsc->image_area.x1));
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t src_area = {
|
||||
.first_byte = image_first_byte,
|
||||
.width_bytes = w * image_cf_size,
|
||||
.height = h,
|
||||
.stride = image_stride
|
||||
};
|
||||
/* make sure the image area is up-to-date in main memory for DMA2D */
|
||||
lv_draw_dma2d_clean_cache(&src_area);
|
||||
#endif
|
||||
|
||||
uint32_t output_offset = (dest_stride / output_cf_size) - w;
|
||||
lv_draw_dma2d_configuration_t conf = {
|
||||
.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_PFC,
|
||||
.w = w,
|
||||
.h = h,
|
||||
|
||||
.output_address = dest_first_pixel,
|
||||
.output_offset = output_offset,
|
||||
.output_cf = output_cf_dma2d,
|
||||
|
||||
.fg_address = image_first_byte,
|
||||
.fg_offset = (image_stride / image_cf_size) - w,
|
||||
.fg_cf = image_cf_dma2d
|
||||
};
|
||||
|
||||
/* only process the background if the image might be transparent */
|
||||
if(lv_color_format_has_alpha(image_cf)) {
|
||||
conf.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING;
|
||||
|
||||
conf.bg_address = dest_first_pixel;
|
||||
conf.bg_offset = output_offset;
|
||||
conf.bg_cf = output_cf_dma2d;
|
||||
}
|
||||
|
||||
/* Alpha channel should be treated as 0xFF if the cf is XRGB */
|
||||
if(image_cf == LV_COLOR_FORMAT_XRGB8888) {
|
||||
conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
|
||||
conf.fg_alpha = 0xff;
|
||||
}
|
||||
if(output_cf == LV_COLOR_FORMAT_XRGB8888) {
|
||||
conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
|
||||
conf.bg_alpha = 0xff;
|
||||
}
|
||||
|
||||
lv_draw_dma2d_configure_and_start_transfer(&conf);
|
||||
}
|
||||
|
||||
static void lv_draw_dma2d_image_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area)
|
||||
{
|
||||
LV_UNUSED(sup);
|
||||
LV_UNUSED(img_coords);
|
||||
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
|
||||
void * dest_first_pixel = lv_draw_layer_go_to_xy(layer,
|
||||
clipped_img_area->x1 - layer->buf_area.x1,
|
||||
clipped_img_area->y1 - layer->buf_area.y1);
|
||||
int32_t dest_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format);
|
||||
|
||||
int32_t w = lv_area_get_width(clipped_img_area);
|
||||
int32_t h = lv_area_get_height(clipped_img_area);
|
||||
|
||||
lv_color_format_t output_cf = layer->color_format;
|
||||
uint32_t output_cf_size = lv_color_format_get_size(output_cf);
|
||||
lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf);
|
||||
|
||||
const lv_draw_buf_t * decoded = decoder_dsc->decoded;
|
||||
const uint8_t * src_buf = decoded->data;
|
||||
uint32_t image_stride = decoded->header.stride;
|
||||
lv_color_format_t image_cf = decoded->header.cf;
|
||||
lv_opa_t opa = draw_dsc->opa;
|
||||
lv_draw_dma2d_fgbg_cf_t image_cf_dma2d = (lv_draw_dma2d_fgbg_cf_t) lv_draw_dma2d_cf_to_dma2d_output_cf(image_cf);
|
||||
uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf);
|
||||
if(image_stride == 0) image_stride = image_cf_size * decoded->header.w;
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t dest_area = {
|
||||
.first_byte = dest_first_pixel,
|
||||
.width_bytes = w * output_cf_size,
|
||||
.height = h,
|
||||
.stride = dest_stride
|
||||
};
|
||||
lv_draw_dma2d_unit_t * u = (lv_draw_dma2d_unit_t *) t->draw_unit;
|
||||
lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t));
|
||||
/* make sure the background area DMA2D is blending is up-to-date in main memory */
|
||||
lv_draw_dma2d_clean_cache(&dest_area);
|
||||
#endif
|
||||
|
||||
const void * image_first_byte = src_buf
|
||||
+ (image_stride * (clipped_img_area->y1 - draw_dsc->image_area.y1))
|
||||
+ (image_cf_size * (clipped_img_area->x1 - draw_dsc->image_area.x1));
|
||||
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t src_area = {
|
||||
.first_byte = image_first_byte,
|
||||
.width_bytes = w * image_cf_size,
|
||||
.height = h,
|
||||
.stride = image_stride
|
||||
};
|
||||
/* make sure the image area is up-to-date in main memory for DMA2D */
|
||||
lv_draw_dma2d_clean_cache(&src_area);
|
||||
#endif
|
||||
|
||||
uint32_t output_offset = (dest_stride / output_cf_size) - w;
|
||||
lv_draw_dma2d_configuration_t conf = {
|
||||
.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING,
|
||||
.w = w,
|
||||
.h = h,
|
||||
|
||||
.output_address = dest_first_pixel,
|
||||
.output_offset = output_offset,
|
||||
.output_cf = output_cf_dma2d,
|
||||
|
||||
.fg_address = image_first_byte,
|
||||
.fg_offset = (image_stride / image_cf_size) - w,
|
||||
.fg_cf = image_cf_dma2d,
|
||||
.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_MULTIPLY_IMAGE_ALPHA_CHANNEL,
|
||||
.fg_alpha = opa,
|
||||
|
||||
.bg_address = dest_first_pixel,
|
||||
.bg_offset = output_offset,
|
||||
.bg_cf = output_cf_dma2d,
|
||||
};
|
||||
|
||||
/* Alpha channel should be treated as 0xFF if the cf is XRGB */
|
||||
if(image_cf == LV_COLOR_FORMAT_XRGB8888) {
|
||||
conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
|
||||
}
|
||||
if(output_cf == LV_COLOR_FORMAT_XRGB8888) {
|
||||
conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
|
||||
conf.bg_alpha = 0xff;
|
||||
}
|
||||
|
||||
lv_draw_dma2d_configure_and_start_transfer(&conf);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_DMA2D*/
|
||||
155
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_private.h
Normal file
155
inc/lvgl/src/draw/dma2d/lv_draw_dma2d_private.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @file lv_draw_dma2d_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_DMA2D_PRIVATE_H
|
||||
#define LV_DRAW_DMA2D_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_dma2d.h"
|
||||
#if LV_USE_DRAW_DMA2D
|
||||
|
||||
#include "../lv_draw_private.h"
|
||||
#include "../sw/lv_draw_sw.h"
|
||||
#include LV_DRAW_DMA2D_HAL_INCLUDE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_DRAW_DMA2D_INTERRUPT && LV_USE_OS
|
||||
#define LV_DRAW_DMA2D_ASYNC 1
|
||||
#else
|
||||
#define LV_DRAW_DMA2D_ASYNC 0
|
||||
#endif
|
||||
|
||||
#if defined(__CORTEX_M) && ((__CORTEX_M == 7) || (__CORTEX_M == 55))
|
||||
#define LV_DRAW_DMA2D_CACHE 1
|
||||
#else
|
||||
#define LV_DRAW_DMA2D_CACHE 0
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_DMA2D_OUTPUT_CF_ARGB8888 = 0,
|
||||
LV_DRAW_DMA2D_OUTPUT_CF_RGB888,
|
||||
LV_DRAW_DMA2D_OUTPUT_CF_RGB565,
|
||||
LV_DRAW_DMA2D_OUTPUT_CF_ARGB1555,
|
||||
LV_DRAW_DMA2D_OUTPUT_CF_ARGB4444
|
||||
} lv_draw_dma2d_output_cf_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_DMA2D_FGBG_CF_ARGB8888 = 0,
|
||||
LV_DRAW_DMA2D_FGBG_CF_RGB888,
|
||||
LV_DRAW_DMA2D_FGBG_CF_RGB565,
|
||||
LV_DRAW_DMA2D_FGBG_CF_ARGB1555,
|
||||
LV_DRAW_DMA2D_FGBG_CF_ARGB4444,
|
||||
LV_DRAW_DMA2D_FGBG_CF_L8,
|
||||
LV_DRAW_DMA2D_FGBG_CF_AL44,
|
||||
LV_DRAW_DMA2D_FGBG_CF_AL88,
|
||||
LV_DRAW_DMA2D_FGBG_CF_L4,
|
||||
LV_DRAW_DMA2D_FGBG_CF_A8,
|
||||
LV_DRAW_DMA2D_FGBG_CF_A4,
|
||||
LV_DRAW_DMA2D_FGBG_CF_YCBCR
|
||||
} lv_draw_dma2d_fgbg_cf_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY = 0,
|
||||
LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_PFC,
|
||||
LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING,
|
||||
LV_DRAW_DMA2D_MODE_REGISTER_TO_MEMORY,
|
||||
LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING_AND_FIXED_COLOR_FG,
|
||||
LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING_AND_FIXED_COLOR_BG
|
||||
} lv_draw_dma2d_mode_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_DMA2D_ALPHA_MODE_NO_MODIFY_IMAGE_ALPHA_CHANNEL = 0,
|
||||
LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL,
|
||||
LV_DRAW_DMA2D_ALPHA_MODE_MULTIPLY_IMAGE_ALPHA_CHANNEL
|
||||
} lv_draw_dma2d_alpha_mode_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_dma2d_mode_t mode;
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
|
||||
void * output_address;
|
||||
uint32_t output_offset;
|
||||
lv_draw_dma2d_output_cf_t output_cf;
|
||||
|
||||
uint32_t reg_to_mem_mode_color;
|
||||
|
||||
const void * fg_address;
|
||||
uint32_t fg_offset;
|
||||
lv_draw_dma2d_fgbg_cf_t fg_cf;
|
||||
uint32_t fg_color;
|
||||
uint32_t fg_alpha_mode;
|
||||
uint32_t fg_alpha;
|
||||
|
||||
const void * bg_address;
|
||||
uint32_t bg_offset;
|
||||
lv_draw_dma2d_fgbg_cf_t bg_cf;
|
||||
uint32_t bg_color;
|
||||
uint32_t bg_alpha_mode;
|
||||
uint32_t bg_alpha;
|
||||
|
||||
} lv_draw_dma2d_configuration_t;
|
||||
|
||||
typedef struct {
|
||||
const void * first_byte;
|
||||
uint32_t width_bytes;
|
||||
uint32_t height;
|
||||
uint32_t stride;
|
||||
} lv_draw_dma2d_cache_area_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * volatile task_act;
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
lv_draw_dma2d_cache_area_t writing_area;
|
||||
#endif
|
||||
#if LV_DRAW_DMA2D_ASYNC
|
||||
lv_thread_sync_t interrupt_signal;
|
||||
#endif
|
||||
} lv_draw_dma2d_unit_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_dma2d_opaque_fill(lv_draw_task_t * t, void * first_pixel, int32_t w, int32_t h, int32_t stride);
|
||||
void lv_draw_dma2d_fill(lv_draw_task_t * t, void * first_pixel, int32_t w, int32_t h, int32_t stride);
|
||||
void lv_draw_dma2d_opaque_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
void lv_draw_dma2d_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
lv_draw_dma2d_output_cf_t lv_draw_dma2d_cf_to_dma2d_output_cf(lv_color_format_t cf);
|
||||
uint32_t lv_draw_dma2d_color_to_dma2d_color(lv_draw_dma2d_output_cf_t cf, lv_color_t color);
|
||||
void lv_draw_dma2d_configure_and_start_transfer(const lv_draw_dma2d_configuration_t * conf);
|
||||
#if LV_DRAW_DMA2D_CACHE
|
||||
void lv_draw_dma2d_invalidate_cache(const lv_draw_dma2d_cache_area_t * mem_area);
|
||||
void lv_draw_dma2d_clean_cache(const lv_draw_dma2d_cache_area_t * mem_area);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_DMA2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_DMA2D_PRIVATE_H*/
|
||||
201
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa.c
Normal file
201
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* @file lv_draw_ppa.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_ppa_private.h"
|
||||
#include "lv_draw_ppa.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_PPA 80
|
||||
#define DRAW_UNIT_PPA_PREF_SCORE 70
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static int32_t ppa_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
static int32_t ppa_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
static int32_t ppa_delete(lv_draw_unit_t * draw_unit);
|
||||
static void ppa_execute_drawing(lv_draw_ppa_unit_t * u);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_ppa_init(void)
|
||||
{
|
||||
esp_err_t res;
|
||||
ppa_client_config_t cfg = {0};
|
||||
|
||||
/* Create draw unit */
|
||||
lv_draw_buf_ppa_init_handlers();
|
||||
lv_draw_ppa_unit_t * draw_ppa_unit = lv_draw_create_unit(sizeof(lv_draw_ppa_unit_t));
|
||||
draw_ppa_unit->base_unit.evaluate_cb = ppa_evaluate;
|
||||
draw_ppa_unit->base_unit.dispatch_cb = ppa_dispatch;
|
||||
draw_ppa_unit->base_unit.delete_cb = ppa_delete;
|
||||
draw_ppa_unit->base_unit.name = "ESP_PPA";
|
||||
|
||||
/* Register SRM client */
|
||||
cfg.oper_type = PPA_OPERATION_SRM;
|
||||
cfg.max_pending_trans_num = 1;
|
||||
#if (LV_PPA_BURST_LENGTH == 128)
|
||||
cfg.data_burst_length = PPA_DATA_BURST_LENGTH_128;
|
||||
#elif (LV_PPA_BURST_LENGTH == 64)
|
||||
cfg.data_burst_length = PPA_DATA_BURST_LENGTH_64;
|
||||
#elif (LV_PPA_BURST_LENGTH == 32)
|
||||
cfg.data_burst_length = PPA_DATA_BURST_LENGTH_32;
|
||||
#elif (LV_PPA_BURST_LENGTH == 16)
|
||||
cfg.data_burst_length = PPA_DATA_BURST_LENGTH_16;
|
||||
#elif (LV_PPA_BURST_LENGTH == 8)
|
||||
cfg.data_burst_length = PPA_DATA_BURST_LENGTH_8;
|
||||
#else
|
||||
#error "Invalid burst length selection for PPA"
|
||||
#endif
|
||||
|
||||
res = ppa_register_client(&cfg, &draw_ppa_unit->srm_client);
|
||||
LV_ASSERT(res == ESP_OK);
|
||||
|
||||
/* Register Fill client */
|
||||
cfg.oper_type = PPA_OPERATION_FILL;
|
||||
res = ppa_register_client(&cfg, &draw_ppa_unit->fill_client);
|
||||
LV_ASSERT(res == ESP_OK);
|
||||
|
||||
/* Register Blend client */
|
||||
cfg.oper_type = PPA_OPERATION_BLEND;
|
||||
|
||||
res = ppa_register_client(&cfg, &draw_ppa_unit->blend_client);
|
||||
LV_ASSERT(res == ESP_OK);
|
||||
}
|
||||
|
||||
void lv_draw_ppa_deinit(void)
|
||||
{
|
||||
/* No global deinit required */
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static int32_t ppa_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
const lv_draw_dsc_base_t * base = (lv_draw_dsc_base_t *)t->draw_dsc;
|
||||
|
||||
if(!ppa_dest_cf_supported(base->layer->color_format)) return 0;
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL: {
|
||||
const lv_draw_fill_dsc_t * dsc = (lv_draw_fill_dsc_t *)t->draw_dsc;
|
||||
if((dsc->radius != 0 || dsc->grad.dir != LV_GRAD_DIR_NONE)) return 0;
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MAX) return 0;
|
||||
|
||||
if(t->preference_score > DRAW_UNIT_PPA_PREF_SCORE) {
|
||||
t->preference_score = DRAW_UNIT_PPA_PREF_SCORE;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_PPA;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LV_USE_PPA_IMG
|
||||
case LV_DRAW_TASK_TYPE_IMAGE: {
|
||||
lv_draw_image_dsc_t * dsc = t->draw_dsc;
|
||||
if(!(dsc->header.cf < LV_COLOR_FORMAT_PROPRIETARY_START
|
||||
&& dsc->clip_radius == 0
|
||||
&& dsc->bitmap_mask_src == NULL
|
||||
&& dsc->sup == NULL
|
||||
&& dsc->tile == 0
|
||||
&& dsc->blend_mode == LV_BLEND_MODE_NORMAL
|
||||
&& dsc->recolor_opa <= LV_OPA_MIN
|
||||
&& dsc->opa <= (lv_opa_t)LV_OPA_MAX
|
||||
&& dsc->skew_y == 0
|
||||
&& dsc->skew_x == 0
|
||||
&& dsc->scale_x == 256
|
||||
&& dsc->scale_y == 256
|
||||
&& dsc->rotation == 0
|
||||
&& lv_image_src_get_type(dsc->src) == LV_IMAGE_SRC_VARIABLE
|
||||
&& (dsc->header.cf == LV_COLOR_FORMAT_RGB888
|
||||
|| dsc->header.cf == LV_COLOR_FORMAT_RGB565)
|
||||
&& (dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB888
|
||||
|| dsc->base.layer->color_format == LV_COLOR_FORMAT_RGB565))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(t->preference_score > DRAW_UNIT_PPA_PREF_SCORE) {
|
||||
t->preference_score = DRAW_UNIT_PPA_PREF_SCORE;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_PPA;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ppa_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_ppa_unit_t * u = (lv_draw_ppa_unit_t *)draw_unit;
|
||||
if(u->task_act) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_PPA);
|
||||
if(!t || t->preferred_draw_unit_id != DRAW_UNIT_ID_PPA) return LV_DRAW_UNIT_IDLE;
|
||||
if(lv_draw_layer_alloc_buf(layer) == NULL) return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
u->task_act = t;
|
||||
u->task_act->draw_unit = draw_unit;
|
||||
|
||||
ppa_execute_drawing(u);
|
||||
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_FINISHED;
|
||||
u->task_act = NULL;
|
||||
lv_draw_dispatch_request();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t ppa_delete(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
lv_draw_ppa_unit_t * u = (lv_draw_ppa_unit_t *)draw_unit;
|
||||
ppa_unregister_client(u->srm_client);
|
||||
ppa_unregister_client(u->fill_client);
|
||||
ppa_unregister_client(u->blend_client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ppa_execute_drawing(lv_draw_ppa_unit_t * u)
|
||||
{
|
||||
lv_draw_task_t * t = u->task_act;
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
lv_draw_buf_t * buf = layer->draw_buf;
|
||||
lv_area_t area;
|
||||
|
||||
if(!lv_area_intersect(&area, &t->area, &t->clip_area)) return;
|
||||
lv_draw_buf_invalidate_cache(buf, &area);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_ppa_fill(t, (lv_draw_fill_dsc_t *)t->draw_dsc, &area);
|
||||
lv_draw_buf_invalidate_cache(buf, &area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_ppa_img(t, (lv_draw_image_dsc_t *)t->draw_dsc, &area);
|
||||
lv_draw_buf_invalidate_cache(buf, &area);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_PPA*/
|
||||
57
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa.h
Normal file
57
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file lv_draw_ppa.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_PPA_H
|
||||
#define LV_DRAW_PPA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
|
||||
#include "../../lv_draw_private.h"
|
||||
#include "../../../display/lv_display_private.h"
|
||||
#include "../../../misc/lv_area_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_ppa_init(void);
|
||||
void lv_draw_ppa_deinit(void);
|
||||
void lv_draw_buf_ppa_init_handlers(void);
|
||||
|
||||
void lv_draw_ppa_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_ppa_img(lv_draw_task_t * t, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_PPA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_PPA_H */
|
||||
46
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_buf.c
Normal file
46
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_buf.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file lv_draw_ppa_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_ppa_private.h"
|
||||
#include "lv_draw_ppa.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
#include LV_STDINT_INCLUDE
|
||||
#include "../../lv_draw_buf_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
*********************/
|
||||
static void invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
*********************/
|
||||
void lv_draw_buf_ppa_init_handlers(void)
|
||||
{
|
||||
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
|
||||
handlers->invalidate_cache_cb = invalidate_cache;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
*********************/
|
||||
|
||||
static void invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
|
||||
{
|
||||
esp_cache_msync(draw_buf->data, draw_buf->data_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_TYPE_DATA);
|
||||
}
|
||||
#endif /* LV_USE_PPA */
|
||||
48
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_fill.c
Normal file
48
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_fill.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file lv_draw_ppa_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lv_draw_ppa_private.h"
|
||||
#include "lv_draw_ppa.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
|
||||
void lv_draw_ppa_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
ppa_fill_oper_config_t fill_cfg = {0};
|
||||
lv_draw_ppa_unit_t * u = (lv_draw_ppa_unit_t *)t->draw_unit;
|
||||
lv_draw_buf_t * draw_buf = t->target_layer->draw_buf;
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -t->target_layer->buf_area.x1, -t->target_layer->buf_area.y1);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, &t->clip_area);
|
||||
lv_area_move(&rel_clip_area, -t->target_layer->buf_area.x1, -t->target_layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
if(!lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
fill_cfg.fill_argb_color.val = lv_color_to_u32(dsc->color);
|
||||
fill_cfg.out.block_offset_x = blend_area.x1;
|
||||
fill_cfg.out.block_offset_y = blend_area.y1;
|
||||
fill_cfg.out.fill_cm = lv_color_format_to_ppa_fill(draw_buf->header.cf);
|
||||
fill_cfg.fill_block_w = lv_area_get_width(&blend_area);
|
||||
fill_cfg.fill_block_h = lv_area_get_height(&blend_area);
|
||||
fill_cfg.out.buffer = draw_buf->data;
|
||||
fill_cfg.out.buffer_size = draw_buf->data_size;
|
||||
fill_cfg.out.pic_w = draw_buf->header.w;
|
||||
fill_cfg.out.pic_h = draw_buf->header.h;;
|
||||
fill_cfg.mode = PPA_TRANS_MODE_BLOCKING;
|
||||
|
||||
esp_err_t ret = ppa_do_fill(u->fill_client, &fill_cfg);
|
||||
if(ret != ESP_OK) {
|
||||
LV_LOG_ERROR("PPA fill failed: %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LV_USE_PPA */
|
||||
114
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_img.c
Normal file
114
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_img.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @file lv_draw_ppa_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lv_draw_ppa_private.h"
|
||||
#include "lv_draw_ppa.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
|
||||
#include "../../lv_draw_image_private.h"
|
||||
#include "../../lv_image_decoder_private.h"
|
||||
|
||||
static void lv_draw_img_ppa_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area);
|
||||
|
||||
|
||||
void lv_draw_ppa_img(lv_draw_task_t * t, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
lv_draw_image_normal_helper(t, dsc, coords, lv_draw_img_ppa_core, NULL);
|
||||
}
|
||||
|
||||
static void lv_draw_img_ppa_core(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
|
||||
const lv_area_t * img_coords, const lv_area_t * clipped_img_area)
|
||||
{
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
lv_draw_buf_t * draw_buf = layer->draw_buf;
|
||||
const lv_draw_buf_t * decoded = decoder_dsc->decoded;
|
||||
lv_draw_ppa_unit_t * u = (lv_draw_ppa_unit_t *)t->draw_unit;
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, clipped_img_area);
|
||||
lv_area_move(&rel_clip_area, -img_coords->x1, -img_coords->y1);
|
||||
|
||||
lv_area_t rel_img_coords;
|
||||
lv_area_copy(&rel_img_coords, img_coords);
|
||||
lv_area_move(&rel_img_coords, -img_coords->x1, -img_coords->y1);
|
||||
|
||||
lv_area_t src_area;
|
||||
if(!lv_area_intersect(&src_area, &rel_clip_area, &rel_img_coords))
|
||||
return;
|
||||
|
||||
lv_area_t dest_area;
|
||||
lv_area_copy(&dest_area, clipped_img_area);
|
||||
lv_area_move(&dest_area, -t->target_layer->buf_area.x1, -t->target_layer->buf_area.y1);
|
||||
|
||||
const uint8_t * src_buf = decoded->data;
|
||||
lv_color_format_t src_cf = draw_dsc->header.cf;
|
||||
lv_color_format_t dest_cf = draw_buf->header.cf;
|
||||
uint8_t * dest_buf = draw_buf->data;
|
||||
|
||||
extern const lv_image_dsc_t img_benchmark_lvgl_logo_rgb;
|
||||
|
||||
ppa_blend_oper_config_t cfg = {
|
||||
.in_bg = {
|
||||
.buffer = (void *)src_buf,
|
||||
.pic_w = draw_dsc->header.w,
|
||||
.pic_h = draw_dsc->header.h,
|
||||
.block_w = lv_area_get_width(clipped_img_area),
|
||||
.block_h = lv_area_get_height(clipped_img_area),
|
||||
.block_offset_x = src_area.x1,
|
||||
.block_offset_y = src_area.y1,
|
||||
.blend_cm = lv_color_format_to_ppa_blend(src_cf),
|
||||
},
|
||||
.bg_rgb_swap = false,
|
||||
.bg_byte_swap = false,
|
||||
.bg_alpha_update_mode = PPA_ALPHA_FIX_VALUE,
|
||||
.bg_alpha_fix_val = 0xFF,
|
||||
.bg_ck_en = false,
|
||||
.in_fg = {
|
||||
.buffer = (void *)dest_buf,
|
||||
.pic_w = draw_dsc->header.w,
|
||||
.pic_h = draw_dsc->header.h,
|
||||
.block_w = lv_area_get_width(clipped_img_area),
|
||||
.block_h = lv_area_get_height(clipped_img_area),
|
||||
.block_offset_x = src_area.x1,
|
||||
.block_offset_y = src_area.y1,
|
||||
.blend_cm = PPA_BLEND_COLOR_MODE_A8,
|
||||
},
|
||||
.fg_fix_rgb_val = {
|
||||
.r = 0,
|
||||
.g = 0,
|
||||
.b = 0,
|
||||
},
|
||||
.fg_rgb_swap = false,
|
||||
.fg_byte_swap = false,
|
||||
.fg_alpha_update_mode = PPA_ALPHA_FIX_VALUE,
|
||||
.fg_alpha_fix_val = 0,
|
||||
.fg_ck_en = false,
|
||||
.out = {
|
||||
.buffer = dest_buf,
|
||||
.buffer_size = draw_buf->data_size,
|
||||
.pic_w = draw_buf->header.w,
|
||||
.pic_h = draw_buf->header.h,
|
||||
.block_offset_x = dest_area.x1,
|
||||
.block_offset_y = dest_area.y1,
|
||||
.blend_cm = lv_color_format_to_ppa_blend(dest_cf),
|
||||
},
|
||||
.mode = PPA_TRANS_MODE_BLOCKING,
|
||||
.user_data = u,
|
||||
};
|
||||
|
||||
esp_err_t ret = ppa_do_blend(u->blend_client, &cfg);
|
||||
if(ret != ESP_OK) {
|
||||
LV_LOG_WARN("PPA draw_img blend failed: %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LV_USE_PPA */
|
||||
177
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_private.h
Normal file
177
inc/lvgl/src/draw/espressif/ppa/lv_draw_ppa_private.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @file lv_draw_ppa_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_PPA_PRIVATE_H
|
||||
#define LV_DRAW_PPA_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_PPA
|
||||
#if LV_PPA_NONBLOCKING_OPS
|
||||
#error "PPA draw in nonblocking is experimental and not supported yet, please make it to 0!"
|
||||
#endif
|
||||
|
||||
#ifndef LV_PPA_NONBLOCKING_OPS
|
||||
#define LV_PPA_NONBLOCKING_OPS 0
|
||||
#endif
|
||||
|
||||
#include LV_STDDEF_INCLUDE
|
||||
#include LV_STDBOOL_INCLUDE
|
||||
#include LV_STDINT_INCLUDE
|
||||
|
||||
#include "../../../misc/lv_color.h"
|
||||
#include "../../../misc/lv_log.h"
|
||||
#include "../../lv_draw_private.h"
|
||||
#include "../../../display/lv_display_private.h"
|
||||
#include "../../../misc/lv_area_private.h"
|
||||
|
||||
/* The ppa driver depends heavily on the esp-idf headers*/
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if (CONFIG_LV_DRAW_BUF_ALIGN != CONFIG_CACHE_L2_CACHE_LINE_SIZE)
|
||||
#error "CONFIG_LV_DRAW_BUF_ALIGN must be equal to CONFIG_CACHE_L2_CACHE_LINE_SIZE!"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CONFIG_SOC_PPA_SUPPORTED
|
||||
#error "This SoC does not support PPA"
|
||||
#endif
|
||||
|
||||
#include "driver/ppa.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_err.h"
|
||||
#include "hal/color_hal.h"
|
||||
#include "esp_cache.h"
|
||||
#include "esp_log.h"
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct lv_draw_ppa_unit {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * task_act;
|
||||
ppa_client_handle_t srm_client;
|
||||
ppa_client_handle_t fill_client;
|
||||
ppa_client_handle_t blend_client;
|
||||
uint8_t * buf;
|
||||
} lv_draw_ppa_unit_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool ppa_src_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static inline bool ppa_dest_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static inline ppa_fill_color_mode_t lv_color_format_to_ppa_fill(lv_color_format_t lv_fmt)
|
||||
{
|
||||
switch(lv_fmt) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
return PPA_FILL_COLOR_MODE_RGB565;
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
return PPA_FILL_COLOR_MODE_RGB888;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
return PPA_FILL_COLOR_MODE_ARGB8888;
|
||||
default:
|
||||
return PPA_FILL_COLOR_MODE_RGB565;
|
||||
}
|
||||
}
|
||||
|
||||
static inline ppa_blend_color_mode_t lv_color_format_to_ppa_blend(lv_color_format_t lv_fmt)
|
||||
{
|
||||
switch(lv_fmt) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
return PPA_BLEND_COLOR_MODE_RGB565;
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
return PPA_BLEND_COLOR_MODE_RGB888;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
return PPA_BLEND_COLOR_MODE_ARGB8888;
|
||||
default:
|
||||
return PPA_BLEND_COLOR_MODE_RGB565;
|
||||
}
|
||||
}
|
||||
|
||||
static inline ppa_srm_color_mode_t lv_color_format_to_ppa_srm(lv_color_format_t lv_fmt)
|
||||
{
|
||||
switch(lv_fmt) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
return PPA_SRM_COLOR_MODE_RGB565;
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
return PPA_SRM_COLOR_MODE_RGB888;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
return PPA_SRM_COLOR_MODE_ARGB8888;
|
||||
default:
|
||||
return PPA_SRM_COLOR_MODE_RGB565;
|
||||
}
|
||||
}
|
||||
|
||||
#define PPA_ALIGN_UP(x, align) ((((x) + (align) - 1) / (align)) * (align))
|
||||
#define PPA_PTR_ALIGN_UP(p, align) \
|
||||
((void*)(((uintptr_t)(p) + (uintptr_t)((align) - 1)) & ~(uintptr_t)((align) - 1)))
|
||||
|
||||
#define PPA_ALIGN_DOWN(x, align) ((((x) - (align) - 1) / (align)) * (align))
|
||||
#define PPA_PTR_ALIGN_DOWN(p, align) \
|
||||
((void*)(((uintptr_t)(p) - (uintptr_t)((align) - 1)) & ~(uintptr_t)((align) - 1)))
|
||||
|
||||
#endif /* LV_USE_PPA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_PPA_PRIVATE_H */
|
||||
164
inc/lvgl/src/draw/eve/lv_draw_eve.c
Normal file
164
inc/lvgl/src/draw/eve/lv_draw_eve.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @file lv_draw_eve.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 3 dic 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "lv_draw_eve_ram_g.h"
|
||||
#include "lv_draw_eve.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_EVE 9
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void eve_execute_drawing(lv_draw_eve_unit_t * u);
|
||||
|
||||
static int32_t eve_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
|
||||
static int32_t eve_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
static void disp_delete_cb(lv_event_t * e);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_init(void)
|
||||
{
|
||||
lv_draw_eve_unit_t * draw_eve_unit = lv_draw_create_unit(sizeof(lv_draw_eve_unit_t));
|
||||
draw_eve_unit->base_unit.dispatch_cb = eve_dispatch;
|
||||
draw_eve_unit->base_unit.evaluate_cb = eve_evaluate;
|
||||
|
||||
lv_draw_eve_unit_g = draw_eve_unit;
|
||||
}
|
||||
|
||||
void lv_draw_eve_set_display_data(lv_display_t * disp, const lv_draw_eve_parameters_t * params,
|
||||
lv_draw_eve_operation_cb_t op_cb)
|
||||
{
|
||||
if(lv_draw_eve_unit_g == NULL) {
|
||||
LV_LOG_WARN("lv_draw_eve is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_eve_unit_g->disp = disp;
|
||||
lv_draw_eve_unit_g->params = *params; /* make a copy */
|
||||
lv_draw_eve_unit_g->op_cb = op_cb;
|
||||
|
||||
lv_display_add_event_cb(disp, disp_delete_cb, LV_EVENT_DELETE, NULL);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static int32_t eve_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_eve_unit_t * draw_eve_unit = (lv_draw_eve_unit_t *) draw_unit;
|
||||
|
||||
lv_draw_task_t * t = NULL;
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_EVE);
|
||||
if(t == NULL) return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
draw_eve_unit->task_act = t;
|
||||
|
||||
eve_execute_drawing(draw_eve_unit);
|
||||
|
||||
draw_eve_unit->task_act->state = LV_DRAW_TASK_STATE_FINISHED;
|
||||
draw_eve_unit->task_act = NULL;
|
||||
|
||||
/*The draw unit is free now. Request a new dispatching as it can get a new task*/
|
||||
lv_draw_dispatch_request();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t eve_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
|
||||
{
|
||||
LV_UNUSED(draw_unit);
|
||||
|
||||
if(((lv_draw_dsc_base_t *)task->draw_dsc)->user_data == NULL) {
|
||||
task->preference_score = 0;
|
||||
task->preferred_draw_unit_id = DRAW_UNIT_ID_EVE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void eve_execute_drawing(lv_draw_eve_unit_t * u)
|
||||
{
|
||||
lv_draw_task_t * t = u->task_act;
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_line_iterate(t, t->draw_dsc, lv_draw_eve_line);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
lv_draw_eve_border(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_eve_fill(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_eve_image(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_eve_label(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
lv_draw_eve_arc(t, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||
lv_draw_eve_triangle(t, t->draw_dsc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void disp_delete_cb(lv_event_t * e)
|
||||
{
|
||||
lv_draw_eve_unit_g->disp = NULL;
|
||||
lv_draw_eve_unit_g = NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
57
inc/lvgl/src/draw/eve/lv_draw_eve.h
Normal file
57
inc/lvgl/src/draw/eve/lv_draw_eve.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file lv_draw_eve.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 3 dic 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_EVE_H
|
||||
#define LV_DRAW_EVE_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "lv_draw_eve_target.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_init(void);
|
||||
|
||||
void lv_draw_eve_set_display_data(lv_display_t * disp, const lv_draw_eve_parameters_t * params,
|
||||
lv_draw_eve_operation_cb_t op_cb);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* LV_DRAW_EVE_H */
|
||||
325
inc/lvgl/src/draw/eve/lv_draw_eve_arc.c
Normal file
325
inc/lvgl/src/draw/eve/lv_draw_eve_arc.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* @file lv_draw_eve_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 11 dic 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../lv_draw_arc.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords);
|
||||
static bool is_same_quadrant(int16_t start_angle, int16_t end_angle) ;
|
||||
static void draw_rounded_end(lv_point_t center, int32_t radius, int32_t angle, int32_t width);
|
||||
static void lv_draw_eve_mask_angle(const lv_draw_arc_dsc_t * dsc, int32_t vertex_x, int32_t vertex_y,
|
||||
int32_t start_angle, int32_t end_angle);
|
||||
static lv_eve_primitive_t get_mask_direction(int16_t angle);
|
||||
static int32_t chord_length(int16_t radius, int16_t angle_degrees);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
draw_eve_arc(t, dsc, coords);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
static int32_t chord_length(int16_t radius, int16_t angle_degrees)
|
||||
{
|
||||
angle_degrees %= 360;
|
||||
if(angle_degrees < 0) angle_degrees += 360;
|
||||
int32_t sin_value = lv_trigo_sin(angle_degrees / 2);
|
||||
int64_t chord_length = 2 * radius * sin_value / 32768.0;
|
||||
return (int32_t)chord_length ;
|
||||
}
|
||||
|
||||
|
||||
static lv_eve_primitive_t get_mask_direction(int16_t angle)
|
||||
{
|
||||
if(angle >= 315 || angle < 45) {
|
||||
return LV_EVE_PRIMITIVE_EDGE_STRIP_R;
|
||||
}
|
||||
if(angle >= 45 && angle < 135) {
|
||||
return LV_EVE_PRIMITIVE_EDGE_STRIP_B;
|
||||
}
|
||||
if(angle >= 135 && angle < 225) {
|
||||
return LV_EVE_PRIMITIVE_EDGE_STRIP_L;
|
||||
}
|
||||
if(angle >= 225 && angle < 315) {
|
||||
return LV_EVE_PRIMITIVE_EDGE_STRIP_A;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void draw_rounded_end(lv_point_t center, int32_t radius, int32_t angle, int32_t width)
|
||||
{
|
||||
int32_t rounded_y = center.y + ((lv_trigo_sin(angle) * radius) >> LV_TRIGO_SHIFT);
|
||||
int32_t rounded_x = center.x + ((lv_trigo_cos(angle) * radius) >> LV_TRIGO_SHIFT);
|
||||
lv_eve_draw_circle_simple(rounded_x, rounded_y, width);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool is_same_quadrant(int16_t start_angle, int16_t end_angle)
|
||||
{
|
||||
if(start_angle > end_angle) {
|
||||
if((start_angle >= 0 && start_angle < 90) && (end_angle >= 0 && end_angle < 90)) {
|
||||
return true;
|
||||
}
|
||||
else if((start_angle >= 90 && start_angle < 180) && (end_angle >= 90 && end_angle < 180)) {
|
||||
return true;
|
||||
}
|
||||
else if((start_angle >= 180 && start_angle < 270) && (end_angle >= 180 && end_angle < 270)) {
|
||||
return true;
|
||||
}
|
||||
else if((start_angle >= 270 && start_angle < 360) && (end_angle >= 270 && end_angle < 360)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void lv_draw_eve_mask_angle(const lv_draw_arc_dsc_t * dsc, int32_t vertex_x, int32_t vertex_y,
|
||||
int32_t start_angle, int32_t end_angle)
|
||||
{
|
||||
|
||||
/*Constrain the input angles*/
|
||||
|
||||
|
||||
if(start_angle < 0)
|
||||
start_angle = 0;
|
||||
else if(start_angle > 359)
|
||||
start_angle = 359;
|
||||
|
||||
if(end_angle < 0)
|
||||
end_angle = 0;
|
||||
else if(end_angle > 359)
|
||||
end_angle = 359;
|
||||
|
||||
LV_ASSERT_MSG(start_angle >= 0 && start_angle <= 360, "Unexpected start angle");
|
||||
|
||||
int32_t mid_angle_op;
|
||||
int32_t angle_range;
|
||||
int32_t mask_dir_start;
|
||||
int32_t mask_dir_end;
|
||||
lv_point_t start;
|
||||
lv_point_t end;
|
||||
lv_point_t angle_range_op;
|
||||
|
||||
if(end_angle > start_angle) {
|
||||
angle_range = LV_ABS(end_angle - start_angle);
|
||||
}
|
||||
else {
|
||||
angle_range = 360 - start_angle + end_angle;
|
||||
}
|
||||
|
||||
mid_angle_op = (angle_range / 2) + start_angle + 180;
|
||||
mid_angle_op = mid_angle_op % 360;
|
||||
|
||||
mask_dir_end = LV_ABS(((360 - angle_range) / 4) + end_angle);
|
||||
mask_dir_start = LV_ABS(((360 - angle_range) / 4) + mid_angle_op);
|
||||
|
||||
mask_dir_start = mask_dir_start % 360;
|
||||
mask_dir_end = mask_dir_end % 360;
|
||||
|
||||
start.y = (lv_trigo_sin(start_angle) >> 5) + vertex_y;
|
||||
start.x = (lv_trigo_cos(start_angle) >> 5) + vertex_x;
|
||||
|
||||
end.y = (lv_trigo_sin(end_angle) >> 5) + vertex_y;
|
||||
end.x = (lv_trigo_cos(end_angle) >> 5) + vertex_x;
|
||||
|
||||
angle_range_op.y = (lv_trigo_sin(mid_angle_op) >> 5) + vertex_y;
|
||||
angle_range_op.x = (lv_trigo_cos(mid_angle_op) >> 5) + vertex_x;
|
||||
|
||||
if(angle_range <= 180) {
|
||||
/* Two sides mask and 6 vertex points */
|
||||
|
||||
/* Masking end angle */
|
||||
lv_eve_primitive_t edge = get_mask_direction(mask_dir_end);
|
||||
lv_eve_primitive(edge); /* Side one */
|
||||
lv_eve_vertex_2f(angle_range_op.x, angle_range_op.y);
|
||||
lv_eve_vertex_2f(vertex_x, vertex_y);
|
||||
lv_eve_vertex_2f(end.x, end.y);
|
||||
|
||||
/* Masking start angle */
|
||||
edge = get_mask_direction(mask_dir_start);
|
||||
lv_eve_primitive(edge); /* Side two */
|
||||
lv_eve_vertex_2f(angle_range_op.x, angle_range_op.y);
|
||||
lv_eve_vertex_2f(vertex_x, vertex_y);
|
||||
lv_eve_vertex_2f(start.x, start.y);
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
if(is_same_quadrant(start_angle,
|
||||
end_angle)) { /* "It is not an optimal implementation for the case where both angles (start and end) are in the same quadrant */
|
||||
/* todo */
|
||||
lv_point_t end_line_cntr;
|
||||
lv_point_t start_line_cntr;
|
||||
|
||||
lv_point_t end_line_brd;
|
||||
lv_point_t start_line_brd;
|
||||
|
||||
int16_t chord = chord_length(dsc->radius, 360 - angle_range);
|
||||
int16_t w = ((chord / 4) < 1) ? 1 : chord / 4;
|
||||
int16_t r_width = w;
|
||||
|
||||
end_line_brd.y = vertex_y + ((lv_trigo_sin(end_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
|
||||
end_line_brd.x = vertex_x + ((lv_trigo_cos(end_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
|
||||
|
||||
start_line_brd.y = vertex_y + ((lv_trigo_sin(start_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
|
||||
start_line_brd.x = vertex_x + ((lv_trigo_cos(start_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
|
||||
|
||||
lv_eve_draw_rect_simple(start_line_brd.x, start_line_brd.y, end_line_brd.x, end_line_brd.y, 0);
|
||||
|
||||
start_line_brd.y = start_line_brd.y + ((lv_trigo_sin(start_angle - 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
start_line_brd.x = start_line_brd.x + ((lv_trigo_cos(start_angle - 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
|
||||
end_line_brd.y = end_line_brd.y + ((lv_trigo_sin(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
end_line_brd.x = end_line_brd.x + ((lv_trigo_cos(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
|
||||
end_line_cntr.y = vertex_y + ((lv_trigo_sin(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
end_line_cntr.x = vertex_x + ((lv_trigo_cos(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
|
||||
|
||||
start_line_cntr.y = vertex_y + ((lv_trigo_sin(start_angle + 270) * r_width) >> LV_TRIGO_SHIFT);
|
||||
start_line_cntr.x = vertex_x + ((lv_trigo_cos(start_angle + 270) * r_width) >> LV_TRIGO_SHIFT);
|
||||
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_LINE_STRIP);
|
||||
lv_eve_line_width(r_width * 16);
|
||||
lv_eve_vertex_2f(start_line_cntr.x, start_line_cntr.y);
|
||||
lv_eve_vertex_2f(start_line_brd.x, start_line_brd.y);
|
||||
lv_eve_vertex_2f(end_line_brd.x, end_line_brd.y);
|
||||
lv_eve_vertex_2f(end_line_cntr.x, end_line_cntr.y);
|
||||
|
||||
}
|
||||
else { /* One side mask and 3 vertex points */
|
||||
/* Masking end and start angles */
|
||||
lv_eve_primitive_t edge = get_mask_direction(mid_angle_op);
|
||||
lv_eve_primitive(edge);
|
||||
lv_eve_vertex_2f(end.x, end.y);
|
||||
lv_eve_vertex_2f(vertex_x, vertex_y);
|
||||
lv_eve_vertex_2f(start.x, start.y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(dsc->start_angle == dsc->end_angle)
|
||||
return;
|
||||
|
||||
lv_color_t color = dsc->color;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
lv_point_t center = dsc->center;
|
||||
int32_t width = dsc->width;
|
||||
uint16_t radius_out = dsc->radius;
|
||||
uint16_t radius_in = dsc->radius - dsc->width;
|
||||
int32_t start_angle = (int32_t) dsc->start_angle;
|
||||
int32_t end_angle = (int32_t) dsc->end_angle;
|
||||
|
||||
if(width > radius_out)
|
||||
width = radius_out;
|
||||
|
||||
while(start_angle >= 360)
|
||||
start_angle -= 360;
|
||||
while(end_angle >= 360)
|
||||
end_angle -= 360;
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
|
||||
lv_eve_save_context();
|
||||
|
||||
lv_eve_color(color);
|
||||
lv_eve_color_opa(opa);
|
||||
|
||||
lv_eve_color_mask(0, 0, 0, 1);
|
||||
lv_eve_stencil_func(EVE_ALWAYS, 0, 1);
|
||||
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
|
||||
lv_eve_draw_circle_simple(center.x, center.y, radius_out); /* radius_out */
|
||||
|
||||
lv_eve_blend_func(EVE_ONE, EVE_ZERO);
|
||||
lv_eve_draw_circle_simple(center.x, center.y, radius_in + 2); /* radius_in */
|
||||
|
||||
lv_eve_stencil_func(EVE_ALWAYS, 1, 1);
|
||||
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
|
||||
lv_eve_blend_func(EVE_ZERO, EVE_ONE_MINUS_SRC_ALPHA);
|
||||
lv_eve_color_opa(0XFF);
|
||||
|
||||
/* Start masking arc */
|
||||
|
||||
lv_draw_eve_mask_angle(dsc, center.x, center.y, start_angle, end_angle);
|
||||
|
||||
/* End masking arc */
|
||||
|
||||
lv_eve_draw_circle_simple(center.x, center.y, radius_in); /* radius_in */
|
||||
|
||||
lv_eve_color_mask(1, 1, 1, 1);
|
||||
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
|
||||
lv_eve_draw_circle_simple(center.x, center.y, radius_in); /* radius_in */
|
||||
|
||||
lv_eve_stencil_func(EVE_NOTEQUAL, 1, 0XFF);
|
||||
lv_eve_stencil_op(EVE_KEEP, EVE_KEEP);
|
||||
lv_eve_blend_func(EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
lv_eve_color_opa(opa);
|
||||
lv_eve_draw_circle_simple(center.x, center.y, radius_out); /* radius_out */
|
||||
|
||||
if(dsc->rounded) {
|
||||
lv_eve_stencil_func(EVE_EQUAL, 1, 0XFF);
|
||||
if(opa < 255) {
|
||||
lv_eve_stencil_op(EVE_ZERO, EVE_ZERO);
|
||||
}
|
||||
|
||||
int32_t half_width = width / 2;
|
||||
int32_t adjusted_radius = radius_out - half_width;
|
||||
draw_rounded_end(center, adjusted_radius, end_angle, half_width);
|
||||
draw_rounded_end(center, adjusted_radius, start_angle, half_width);
|
||||
}
|
||||
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
121
inc/lvgl/src/draw/eve/lv_draw_eve_fill.c
Normal file
121
inc/lvgl/src/draw/eve/lv_draw_eve_fill.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @file lv_draw_eve_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 27 mar 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
#include "lv_eve.h"
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
|
||||
int32_t rad = dsc->radius;
|
||||
int32_t bg_w = lv_area_get_width(coords);
|
||||
int32_t bg_h = lv_area_get_height(coords);
|
||||
int32_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, rad);
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
lv_eve_save_context();
|
||||
|
||||
lv_eve_color(dsc->color);
|
||||
lv_eve_color_opa(dsc->opa);
|
||||
|
||||
if(bg_w == bg_h && rad == LV_RADIUS_CIRCLE) {
|
||||
lv_eve_draw_circle_simple(coords->x1 + (bg_w / 2), coords->y1 + (bg_h / 2), real_radius);
|
||||
}
|
||||
else {
|
||||
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, real_radius);
|
||||
}
|
||||
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
|
||||
void lv_draw_eve_border(lv_draw_task_t * t, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->width == 0) return;
|
||||
if(dsc->side == LV_BORDER_SIDE_NONE) return;
|
||||
|
||||
int32_t coords_w = lv_area_get_width(coords);
|
||||
int32_t coords_h = lv_area_get_height(coords);
|
||||
int32_t rout = dsc->radius;
|
||||
int32_t short_side = LV_MIN(coords_w, coords_h);
|
||||
if(rout > short_side >> 1) rout = short_side >> 1;
|
||||
|
||||
/*Get the inner area*/
|
||||
lv_area_t area_inner;
|
||||
lv_area_copy(&area_inner, coords);
|
||||
area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width));
|
||||
area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width));
|
||||
area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width));
|
||||
area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width));
|
||||
|
||||
int32_t rin = rout - dsc->width;
|
||||
if(rin < 0) rin = 0;
|
||||
|
||||
lv_eve_save_context();
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
|
||||
lv_eve_color(dsc->color);
|
||||
lv_eve_color_opa(dsc->opa);
|
||||
|
||||
lv_eve_color_mask(0, 0, 0, 1);
|
||||
lv_eve_stencil_func(EVE_ALWAYS, 0, 1);
|
||||
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
|
||||
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, 0);
|
||||
|
||||
lv_eve_blend_func(EVE_ONE, EVE_ZERO);
|
||||
lv_eve_draw_rect_simple(area_inner.x1 - 2, area_inner.y1 - 1, area_inner.x2 + 1, area_inner.y2 + 2, rin);
|
||||
|
||||
lv_eve_stencil_func(EVE_ALWAYS, 1, 1);
|
||||
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
|
||||
lv_eve_blend_func(EVE_ZERO, EVE_ONE_MINUS_SRC_ALPHA);
|
||||
lv_eve_color_opa(255);
|
||||
lv_eve_draw_rect_simple(area_inner.x1, area_inner.y1, area_inner.x2, area_inner.y2, rin);
|
||||
|
||||
lv_eve_color_mask(1, 1, 1, 1);
|
||||
|
||||
if(dsc->side == LV_BORDER_SIDE_FULL) {
|
||||
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
|
||||
lv_eve_draw_rect_simple(area_inner.x1, area_inner.y1, area_inner.x2, area_inner.y2, rin);
|
||||
}
|
||||
|
||||
lv_eve_stencil_func(EVE_NOTEQUAL, 1, 255);
|
||||
lv_eve_blend_func(EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
lv_eve_color_opa(dsc->opa);
|
||||
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, rout);
|
||||
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
299
inc/lvgl/src/draw/eve/lv_draw_eve_image.c
Normal file
299
inc/lvgl/src/draw/eve/lv_draw_eve_image.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* @file lv_draw_eve_image.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 17 jun 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../lv_draw_image_private.h"
|
||||
#include "lv_draw_eve_ram_g.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void convert_row_rgb565a8_to_argb4444(const uint8_t * src, const uint8_t * src_alpha, uint8_t * dst,
|
||||
uint32_t width);
|
||||
static void convert_row_argb8888_to_argb4444(const uint8_t * src, uint8_t * dst, uint32_t width);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define F16_PIVOT_SHIFT(x) ((int32_t)((((x) >> 1)) * 65536L))
|
||||
#define F16_SCALE_DIV_256(x) ((int32_t)(((x) / 256.0f) * 65536L))
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(!lv_draw_eve_image_src_check(draw_dsc->src)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_image_dsc_t * img_dsc = draw_dsc->src;
|
||||
|
||||
int32_t src_w = img_dsc->header.w;
|
||||
int32_t src_h = img_dsc->header.h;
|
||||
int32_t src_stride = img_dsc->header.stride;
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
|
||||
if(src_stride == 0) {
|
||||
src_stride = src_w * lv_color_format_get_size(src_cf);
|
||||
}
|
||||
|
||||
uint8_t eve_format;
|
||||
int32_t eve_stride;
|
||||
|
||||
switch(src_cf) {
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
eve_format = EVE_L8;
|
||||
eve_stride = src_stride;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
eve_format = EVE_RGB565;
|
||||
eve_stride = src_stride;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
eve_format = EVE_ARGB4;
|
||||
eve_stride = src_w * 2;
|
||||
break;
|
||||
default :
|
||||
LV_ASSERT(0);
|
||||
}
|
||||
|
||||
uint32_t ramg_addr = lv_draw_eve_image_upload_image(true, img_dsc);
|
||||
if(ramg_addr == LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
|
||||
LV_LOG_WARN("Could not load image because space could not be allocated in RAM_G.");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
|
||||
lv_eve_save_context();
|
||||
|
||||
lv_eve_color_opa(draw_dsc->opa);
|
||||
|
||||
if(draw_dsc->recolor_opa > LV_OPA_MIN) {
|
||||
lv_eve_color(lv_color_mix(draw_dsc->recolor, lv_color_white(), draw_dsc->recolor_opa));
|
||||
}
|
||||
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_BITMAPS);
|
||||
lv_eve_bitmap_source(ramg_addr);
|
||||
/*real height and width is mandatory for rotation and scale (Clip Area)*/
|
||||
lv_eve_bitmap_size(EVE_NEAREST, EVE_BORDER, EVE_BORDER, src_w, src_h);
|
||||
|
||||
lv_eve_bitmap_layout(eve_format, eve_stride, src_h);
|
||||
|
||||
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
|
||||
EVE_cmd_dl_burst(CMD_LOADIDENTITY);
|
||||
|
||||
EVE_cmd_translate_burst(F16(coords->x1 - t->clip_area.x1 + draw_dsc->pivot.x),
|
||||
F16(coords->y1 - t->clip_area.y1 + draw_dsc->pivot.y));
|
||||
if(draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
|
||||
/*Image Scale*/
|
||||
EVE_cmd_scale_burst(F16_SCALE_DIV_256(draw_dsc->scale_x), F16_SCALE_DIV_256(draw_dsc->scale_y));
|
||||
}
|
||||
if(draw_dsc->rotation != 0) {
|
||||
/*Image Rotate*/
|
||||
EVE_cmd_rotate_burst(DEGREES(draw_dsc->rotation));
|
||||
}
|
||||
EVE_cmd_translate_burst(-F16(draw_dsc->pivot.x), -F16(draw_dsc->pivot.y));
|
||||
EVE_cmd_dl_burst(CMD_SETMATRIX);
|
||||
EVE_cmd_dl_burst(CMD_LOADIDENTITY);
|
||||
lv_eve_vertex_2f(t->clip_area.x1, t->clip_area.y1);
|
||||
}
|
||||
else {
|
||||
lv_eve_vertex_2f(coords->x1, coords->y1);
|
||||
}
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
bool lv_draw_eve_image_src_check(const void * src)
|
||||
{
|
||||
if(lv_image_src_get_type(src) != LV_IMAGE_SRC_VARIABLE) {
|
||||
LV_LOG_WARN("lv_draw_eve can only render images from variables (not files or symbols) for now.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv_image_dsc_t * img_dsc = src;
|
||||
|
||||
switch(img_dsc->header.cf) {
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
break;
|
||||
default :
|
||||
LV_LOG_WARN("lv_draw_eve can only render L8, RGB565, RGB565A8, and ARGB8888 images for now.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t lv_draw_eve_image_upload_image(bool burst_is_active, const lv_image_dsc_t * img_dsc)
|
||||
{
|
||||
const uint8_t * src_buf = img_dsc->data;
|
||||
int32_t src_w = img_dsc->header.w;
|
||||
int32_t src_h = img_dsc->header.h;
|
||||
int32_t src_stride = img_dsc->header.stride;
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
|
||||
if(src_stride == 0) {
|
||||
src_stride = src_w * lv_color_format_get_size(src_cf);
|
||||
}
|
||||
|
||||
int32_t eve_stride;
|
||||
uint8_t eve_alignment;
|
||||
|
||||
switch(src_cf) {
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
eve_stride = src_stride;
|
||||
eve_alignment = 1;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
eve_stride = src_stride;
|
||||
eve_alignment = 2;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
eve_stride = src_w * 2;
|
||||
eve_alignment = 2;
|
||||
break;
|
||||
default :
|
||||
LV_ASSERT(0);
|
||||
}
|
||||
|
||||
int32_t eve_size = eve_stride * src_h;
|
||||
|
||||
uint32_t ramg_addr;
|
||||
bool img_is_loaded = lv_draw_eve_ramg_get_addr(&ramg_addr, (uintptr_t) src_buf, eve_size, eve_alignment);
|
||||
|
||||
/* New image to load */
|
||||
if(!img_is_loaded && ramg_addr != LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
|
||||
|
||||
/* Load image to RAM_G */
|
||||
|
||||
if(burst_is_active) {
|
||||
EVE_end_cmd_burst();
|
||||
}
|
||||
|
||||
switch(src_cf) {
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
EVE_memWrite_flash_buffer(ramg_addr, src_buf, eve_size);
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8: {
|
||||
uint8_t * tmp_buf = lv_malloc(eve_stride);
|
||||
LV_ASSERT_MALLOC(tmp_buf);
|
||||
const uint8_t * src_alpha_buf = src_buf + src_h * src_stride;
|
||||
int32_t src_alpha_stride = src_stride / 2;
|
||||
for(uint32_t y = 0; y < src_h; y++) {
|
||||
convert_row_rgb565a8_to_argb4444(src_buf + y * src_stride, src_alpha_buf + y * src_alpha_stride, tmp_buf, src_w);
|
||||
EVE_memWrite_flash_buffer(ramg_addr + y * eve_stride, tmp_buf, eve_stride);
|
||||
}
|
||||
lv_free(tmp_buf);
|
||||
break;
|
||||
}
|
||||
case LV_COLOR_FORMAT_ARGB8888: {
|
||||
uint8_t * tmp_buf = lv_malloc(eve_stride);
|
||||
LV_ASSERT_MALLOC(tmp_buf);
|
||||
for(uint32_t y = 0; y < src_h; y++) {
|
||||
convert_row_argb8888_to_argb4444(src_buf + y * src_stride, tmp_buf, src_w);
|
||||
EVE_memWrite_flash_buffer(ramg_addr + y * eve_stride, tmp_buf, eve_stride);
|
||||
}
|
||||
lv_free(tmp_buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LV_ASSERT(0);
|
||||
}
|
||||
|
||||
if(burst_is_active) {
|
||||
EVE_start_cmd_burst();
|
||||
}
|
||||
}
|
||||
|
||||
return ramg_addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void convert_row_rgb565a8_to_argb4444(const uint8_t * src, const uint8_t * src_alpha, uint8_t * dst,
|
||||
uint32_t width)
|
||||
{
|
||||
for(uint32_t x = 0; x < width; x++) {
|
||||
uint16_t rgb565 = ((const uint16_t *) src)[x];
|
||||
|
||||
uint8_t r5 = (rgb565 >> 11) & 0x1F;
|
||||
uint8_t g6 = (rgb565 >> 5) & 0x3F;
|
||||
uint8_t b5 = rgb565 & 0x1F;
|
||||
uint8_t alpha = src_alpha[x];
|
||||
|
||||
uint8_t r4 = r5 >> 1;
|
||||
uint8_t g4 = g6 >> 2;
|
||||
uint8_t b4 = b5 >> 1;
|
||||
uint8_t a4 = alpha >> 4;
|
||||
|
||||
uint16_t argb4444 = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
|
||||
|
||||
dst[2 * x] = argb4444 & 0xFF;
|
||||
dst[2 * x + 1] = (argb4444 >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_row_argb8888_to_argb4444(const uint8_t * src, uint8_t * dst, uint32_t width)
|
||||
{
|
||||
for(uint32_t x = 0; x < width; x++) {
|
||||
uint8_t blue = src[4 * x];
|
||||
uint8_t green = src[4 * x + 1];
|
||||
uint8_t red = src[4 * x + 2];
|
||||
uint8_t alpha = src[4 * x + 3];
|
||||
|
||||
uint8_t r4 = red >> 4;
|
||||
uint8_t g4 = green >> 4;
|
||||
uint8_t b4 = blue >> 4;
|
||||
uint8_t a4 = alpha >> 4;
|
||||
|
||||
uint16_t argb4444 = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
|
||||
|
||||
dst[2 * x] = argb4444 & 0xFF;
|
||||
dst[2 * x + 1] = (argb4444 >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
233
inc/lvgl/src/draw/eve/lv_draw_eve_letter.c
Normal file
233
inc/lvgl/src/draw/eve/lv_draw_eve_letter.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file lv_draw_eve_letter.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../lv_draw_private.h"
|
||||
#include "../lv_draw_label_private.h"
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_draw_eve_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
|
||||
static void font_bitmap_to_ramg(uint32_t addr, const uint8_t * src, uint32_t width,
|
||||
uint32_t height, uint8_t src_stride_align);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define GET_NIBBLE_1(w) ((uint8_t) ((w) >> 4))
|
||||
#define GET_NIBBLE_2(w) ((uint8_t) ((w) & 0xf))
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_label(lv_draw_task_t * t, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
lv_eve_save_context();
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_BITMAPS);
|
||||
lv_draw_label_iterate_characters(t, dsc, coords, lv_draw_eve_letter_cb);
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
bool lv_draw_eve_label_font_check(const lv_font_t * font)
|
||||
{
|
||||
if(font->get_glyph_bitmap != lv_font_get_bitmap_fmt_txt) {
|
||||
LV_LOG_WARN("lv_draw_eve can only render static fonts for now.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv_font_fmt_txt_dsc_t * font_dsc = font->dsc;
|
||||
|
||||
/* Only 4 bpp is supported for now. Support for 1 and 8 bpp can be added. (EVE_L1, EVE_L8) */
|
||||
if(font_dsc->bpp != 4) {
|
||||
LV_LOG_WARN("lv_draw_eve can only render static fonts for now.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t lv_draw_eve_label_upload_glyph(bool burst_is_active, const lv_font_fmt_txt_dsc_t * font_dsc,
|
||||
uint32_t gid_index)
|
||||
{
|
||||
const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = &font_dsc->glyph_dsc[gid_index];
|
||||
const uint8_t * glyph_bitmap = &font_dsc->glyph_bitmap[glyph_dsc->bitmap_index];
|
||||
|
||||
uint16_t g_box_w = glyph_dsc->box_w;
|
||||
uint16_t g_box_h = glyph_dsc->box_h;
|
||||
|
||||
uint16_t g_aligned_stride = (g_box_w + 1) / 2;
|
||||
|
||||
uint32_t glyph_ramg_size = g_aligned_stride * g_box_h;
|
||||
|
||||
uint32_t ramg_addr;
|
||||
uintptr_t glyph_ramg_key = (uintptr_t) glyph_bitmap;
|
||||
bool font_is_loaded = lv_draw_eve_ramg_get_addr(&ramg_addr, glyph_ramg_key, glyph_ramg_size, 1);
|
||||
|
||||
/* If the font is not yet loaded in ramG, load it */
|
||||
if(!font_is_loaded && ramg_addr != LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
|
||||
if(burst_is_active) {
|
||||
EVE_end_cmd_burst();
|
||||
}
|
||||
|
||||
uint8_t glyph_bitmap_stride_align = font_dsc->stride;
|
||||
font_bitmap_to_ramg(ramg_addr, glyph_bitmap, g_box_w, g_box_h, glyph_bitmap_stride_align);
|
||||
|
||||
if(burst_is_active) {
|
||||
EVE_start_cmd_burst();
|
||||
}
|
||||
}
|
||||
|
||||
return ramg_addr;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_draw_eve_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
|
||||
{
|
||||
|
||||
if(fill_draw_dsc && fill_area) {
|
||||
/* draw UNDERLINE and STRIKETHROUGH */
|
||||
lv_eve_draw_rect_simple(fill_area->x1, fill_area->y1, fill_area->x2, fill_area->y2, 0);
|
||||
}
|
||||
|
||||
if(glyph_draw_dsc == NULL)
|
||||
return; /* Important */
|
||||
|
||||
const lv_font_t * font = glyph_draw_dsc->g->resolved_font;
|
||||
|
||||
if(!lv_draw_eve_label_font_check(font)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_font_fmt_txt_dsc_t * font_dsc = font->dsc;
|
||||
uint32_t gid_index = glyph_draw_dsc->g->gid.index;
|
||||
const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = &font_dsc->glyph_dsc[gid_index];
|
||||
|
||||
uint16_t g_box_w = glyph_dsc->box_w;
|
||||
uint16_t g_box_h = glyph_dsc->box_h;
|
||||
|
||||
uint16_t g_aligned_stride = (g_box_w + 1) / 2;
|
||||
|
||||
uint8_t bpp_eve = EVE_L4;
|
||||
|
||||
uint32_t ramg_addr = lv_draw_eve_label_upload_glyph(true, font_dsc, gid_index);
|
||||
if(ramg_addr == LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
|
||||
LV_LOG_WARN("Could not load glyph because space could not be allocated in RAM_G.");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_eve_color_opa(glyph_draw_dsc->opa);
|
||||
lv_eve_color(glyph_draw_dsc->color);
|
||||
|
||||
lv_eve_bitmap_source(ramg_addr);
|
||||
|
||||
lv_eve_bitmap_size(EVE_NEAREST, EVE_BORDER, EVE_BORDER, g_box_w, g_box_h);
|
||||
lv_eve_bitmap_layout(bpp_eve, g_aligned_stride, g_box_h);
|
||||
|
||||
lv_eve_vertex_2f(glyph_draw_dsc->letter_coords->x1, glyph_draw_dsc->letter_coords->y1);
|
||||
}
|
||||
|
||||
static void font_bitmap_to_ramg(uint32_t addr, const uint8_t * src, uint32_t width,
|
||||
uint32_t height, uint8_t src_stride_align)
|
||||
{
|
||||
uint32_t stride = (width + 1) / 2;
|
||||
|
||||
if(src_stride_align == 1 || (src_stride_align == 0 && width % 2 == 0)) {
|
||||
uint32_t size = stride * height;
|
||||
EVE_memWrite_flash_buffer(addr, src, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if(src_stride_align > 0) {
|
||||
uint32_t src_stride = LV_ALIGN_UP(stride, src_stride_align);
|
||||
for(uint32_t y = 0; y < height; y++) {
|
||||
EVE_memWrite_sram_buffer(addr, src, stride);
|
||||
addr += stride;
|
||||
src += src_stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t * row_buf = lv_malloc(stride);
|
||||
LV_ASSERT_MALLOC(row_buf);
|
||||
|
||||
uint32_t src_i = 0;
|
||||
uint8_t nibble_1;
|
||||
uint8_t nibble_2;
|
||||
uint8_t key = 0;
|
||||
|
||||
/* Iterate through each row of the bitmap*/
|
||||
for(uint32_t y = 0; y < height; y++) {
|
||||
/* Iterate through each byte of the row*/
|
||||
uint32_t row_i;
|
||||
for(row_i = 0; row_i < (width / 2); ++row_i) {
|
||||
/*Get the two nibbles from the current byte*/
|
||||
if(key == 0) {
|
||||
nibble_1 = GET_NIBBLE_1(src[src_i]);
|
||||
nibble_2 = GET_NIBBLE_2(src[src_i]);
|
||||
}
|
||||
else {
|
||||
nibble_1 = GET_NIBBLE_2(src[src_i - 1]);
|
||||
nibble_2 = GET_NIBBLE_1(src[src_i]);
|
||||
}
|
||||
|
||||
/*Combine the nibbles and assign the result to the output byte*/
|
||||
row_buf[row_i] = (nibble_1 << 4) | nibble_2;
|
||||
|
||||
src_i++;
|
||||
}
|
||||
|
||||
/*process the last remaining nibble*/
|
||||
row_buf[row_i] =
|
||||
(key == 0) ?
|
||||
(GET_NIBBLE_1(src[src_i])) << 4 | 0x0 : (GET_NIBBLE_2(src[src_i - 1])) << 4 | 0x0;
|
||||
key = (key == 0) ? 1 : 0;
|
||||
src_i += (key == 1) ? 1 : 0;
|
||||
|
||||
EVE_memWrite_sram_buffer(addr, row_buf, stride);
|
||||
addr += stride;
|
||||
}
|
||||
|
||||
lv_free(row_buf);
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
63
inc/lvgl/src/draw/eve/lv_draw_eve_line.c
Normal file
63
inc/lvgl/src/draw/eve/lv_draw_eve_line.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @file lv_draw_eve_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 8 abr 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
#include "lv_eve.h"
|
||||
|
||||
|
||||
void lv_draw_eve_line(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
uint32_t line_w = dsc->width * 8;
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
lv_eve_save_context();
|
||||
lv_eve_color_opa(dsc->opa);
|
||||
lv_eve_color(dsc->color);
|
||||
|
||||
if(dsc->dash_gap || dsc->dash_width) {
|
||||
LV_LOG_WARN("line dash_gap and dash_width not implemented by EVE yet.");
|
||||
}
|
||||
/* Check if it's a vertical or horizontal line without rounding */
|
||||
bool is_vertical = (dsc->p1.x == dsc->p2.x);
|
||||
bool is_horizontal = (dsc->p1.y == dsc->p2.y);
|
||||
bool no_round = (!dsc->round_end || !dsc->round_start);
|
||||
|
||||
if((is_vertical || is_horizontal) && no_round) {
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_RECTS);
|
||||
lv_eve_vertex_2f(dsc->p1.x, dsc->p1.y);
|
||||
lv_eve_vertex_2f(dsc->p2.x, dsc->p2.y);
|
||||
}
|
||||
else {
|
||||
/* Draw inclined line or line with rounding (not possible without rounding)*/
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_LINE_STRIP);
|
||||
lv_eve_line_width(line_w);
|
||||
lv_eve_vertex_2f(dsc->p1.x, dsc->p1.y);
|
||||
lv_eve_vertex_2f(dsc->p2.x, dsc->p2.y);
|
||||
}
|
||||
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
117
inc/lvgl/src/draw/eve/lv_draw_eve_private.h
Normal file
117
inc/lvgl/src/draw/eve/lv_draw_eve_private.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file lv_draw_eve_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_EVE_PRIVATE_H
|
||||
#define LV_DRAW_EVE_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_eve.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "lv_draw_eve_target.h"
|
||||
#include "lv_draw_eve_ram_g.h"
|
||||
#include "../lv_draw_private.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../lv_draw_triangle.h"
|
||||
#include "../lv_draw_line.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../font/fmt_txt/lv_font_fmt_txt.h"
|
||||
#include "../lv_draw_arc.h"
|
||||
|
||||
#if LV_DRAW_EVE_WRITE_BUFFER_SIZE != 0 && LV_DRAW_EVE_WRITE_BUFFER_SIZE < 4
|
||||
#warning LV_DRAW_EVE_WRITE_BUFFER_SIZE cannot be less than 4. Using 0 (buffering disabled).
|
||||
#define LV_DRAW_EVE_WRITE_BUFFER_SIZE_INTERNAL 0
|
||||
#else
|
||||
#define LV_DRAW_EVE_WRITE_BUFFER_SIZE_INTERNAL LV_DRAW_EVE_WRITE_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
uintptr_t key;
|
||||
uint32_t addr;
|
||||
} lv_draw_eve_ramg_hash_table_cell_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t ramg_addr_end;
|
||||
uint32_t hash_table_cell_count;
|
||||
uint32_t hash_table_cells_occupied;
|
||||
lv_draw_eve_ramg_hash_table_cell_t * hash_table;
|
||||
} lv_draw_eve_ramg_t;
|
||||
|
||||
struct _lv_draw_eve_unit_t {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * task_act;
|
||||
lv_display_t * disp;
|
||||
lv_draw_eve_ramg_t ramg;
|
||||
lv_draw_eve_parameters_t params;
|
||||
lv_draw_eve_operation_cb_t op_cb;
|
||||
#if LV_DRAW_EVE_WRITE_BUFFER_SIZE_INTERNAL
|
||||
uint32_t lv_eve_write_buf_len;
|
||||
uint8_t lv_eve_write_buf[LV_DRAW_EVE_WRITE_BUFFER_SIZE_INTERNAL];
|
||||
#endif
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
bool lv_draw_eve_image_src_check(const void * src);
|
||||
uint32_t lv_draw_eve_image_upload_image(bool burst_is_active, const lv_image_dsc_t * img_dsc);
|
||||
|
||||
void lv_draw_eve_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
void lv_draw_eve_border(lv_draw_task_t * t, const lv_draw_border_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_eve_line(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
void lv_draw_eve_label(lv_draw_task_t * t, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
bool lv_draw_eve_label_font_check(const lv_font_t * font);
|
||||
uint32_t lv_draw_eve_label_upload_glyph(bool burst_is_active, const lv_font_fmt_txt_dsc_t * font_dsc,
|
||||
uint32_t gid_index);
|
||||
|
||||
void lv_draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
void lv_draw_eve_triangle(lv_draw_task_t * t, const lv_draw_triangle_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define DEGREES(n) ((65536UL * (n)) / 3600)
|
||||
#define F16(x) ((int32_t)((x) * 65536L))
|
||||
|
||||
#define lv_draw_eve_unit_g (LV_GLOBAL_DEFAULT()->draw_eve_unit)
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_EVE_PRIVATE_H*/
|
||||
221
inc/lvgl/src/draw/eve/lv_draw_eve_ram_g.c
Normal file
221
inc/lvgl/src/draw/eve/lv_draw_eve_ram_g.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* @file lv_draw_eve_ram_g.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 19 nov 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
#include "lv_draw_eve_ram_g.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define RAMG_DEBUG 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void ramg_init(lv_draw_eve_ramg_t * ramg);
|
||||
static uint32_t hash_key(uintptr_t key);
|
||||
static uint32_t fnv_1a_hash(const void * src, size_t len);
|
||||
static void grow_hash_table(lv_draw_eve_ramg_t * ramg);
|
||||
|
||||
#if RAMG_DEBUG
|
||||
static void ramg_debug(lv_draw_eve_ramg_t * ramg, uint32_t key_hash, uint32_t table_index);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_draw_eve_ramg_get_addr(uint32_t * addr_dst, uintptr_t key,
|
||||
uint32_t addr_size, uint32_t addr_align)
|
||||
{
|
||||
LV_ASSERT(key != 0);
|
||||
|
||||
lv_draw_eve_ramg_t * ramg = &lv_draw_eve_unit_g->ramg;
|
||||
|
||||
if(ramg->hash_table_cell_count == 0) {
|
||||
ramg_init(ramg);
|
||||
}
|
||||
|
||||
uint32_t key_hash = hash_key(key);
|
||||
uint32_t table_index = key_hash % ramg->hash_table_cell_count;
|
||||
lv_draw_eve_ramg_hash_table_cell_t * cell;
|
||||
|
||||
while(1) {
|
||||
cell = &ramg->hash_table[table_index];
|
||||
|
||||
if(cell->key == key) {
|
||||
#if RAMG_DEBUG
|
||||
ramg_debug(ramg, key_hash, table_index);
|
||||
#endif
|
||||
|
||||
*addr_dst = cell->addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(cell->key == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
table_index++;
|
||||
if(table_index >= ramg->hash_table_cell_count) table_index = 0;
|
||||
}
|
||||
|
||||
uint32_t addr_ret = LV_ALIGN_UP(ramg->ramg_addr_end, addr_align);
|
||||
uint32_t addr_new_end = addr_ret + addr_size;
|
||||
|
||||
if(addr_new_end > 1024 * 1024) {
|
||||
LV_LOG_WARN("EVE on-chip 1 MB RAM_G for images and fonts has run out.");
|
||||
*addr_dst = LV_DRAW_EVE_RAMG_OUT_OF_RAMG;
|
||||
return false;
|
||||
}
|
||||
|
||||
ramg->ramg_addr_end = addr_new_end;
|
||||
ramg->hash_table_cells_occupied++;
|
||||
|
||||
cell->key = key;
|
||||
cell->addr = addr_ret;
|
||||
*addr_dst = addr_ret;
|
||||
|
||||
#if RAMG_DEBUG
|
||||
ramg_debug(ramg, key_hash, table_index);
|
||||
#endif
|
||||
|
||||
if(ramg->hash_table_cells_occupied > ramg->hash_table_cell_count / 4 * 3) {
|
||||
grow_hash_table(ramg);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void ramg_init(lv_draw_eve_ramg_t * ramg)
|
||||
{
|
||||
ramg->hash_table_cell_count = 32;
|
||||
ramg->hash_table = lv_calloc(32, sizeof(lv_draw_eve_ramg_hash_table_cell_t));
|
||||
LV_ASSERT_MALLOC(ramg->hash_table);
|
||||
}
|
||||
|
||||
static uint32_t hash_key(uintptr_t key)
|
||||
{
|
||||
return fnv_1a_hash(&key, sizeof(key));
|
||||
}
|
||||
|
||||
static uint32_t fnv_1a_hash(const void * src, size_t len)
|
||||
{
|
||||
const uint8_t * src_u8 = src;
|
||||
uint32_t hash = 2166136261u;
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
hash ^= src_u8[i];
|
||||
hash *= 16777619u;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void grow_hash_table(lv_draw_eve_ramg_t * ramg)
|
||||
{
|
||||
uint32_t old_cell_count = ramg->hash_table_cell_count;
|
||||
lv_draw_eve_ramg_hash_table_cell_t * old_hash_table = ramg->hash_table;
|
||||
|
||||
ramg->hash_table_cell_count += ramg->hash_table_cell_count / 2;
|
||||
ramg->hash_table = lv_calloc(ramg->hash_table_cell_count,
|
||||
sizeof(lv_draw_eve_ramg_hash_table_cell_t));
|
||||
LV_ASSERT_MALLOC(ramg->hash_table);
|
||||
|
||||
for(uint32_t i = 0; i < old_cell_count; i++) {
|
||||
lv_draw_eve_ramg_hash_table_cell_t * old_cell = &old_hash_table[i];
|
||||
|
||||
if(old_cell->key == 0) continue;
|
||||
|
||||
uint32_t key_hash = hash_key(old_cell->key);
|
||||
uint32_t new_table_index = key_hash % ramg->hash_table_cell_count;
|
||||
lv_draw_eve_ramg_hash_table_cell_t * new_cell_dst = &ramg->hash_table[new_table_index];
|
||||
|
||||
while(new_cell_dst->key != 0) {
|
||||
new_table_index++;
|
||||
if(new_table_index >= ramg->hash_table_cell_count) new_table_index = 0;
|
||||
new_cell_dst = &ramg->hash_table[new_table_index];
|
||||
}
|
||||
*new_cell_dst = *old_cell;
|
||||
}
|
||||
|
||||
lv_free(old_hash_table);
|
||||
}
|
||||
|
||||
#if RAMG_DEBUG
|
||||
/*
|
||||
Print tables like this:
|
||||
113 kB of RAM_G used
|
||||
================================-==-=====---=---===---=====-=-=-=-==--=======----=-==-==---=--===--=-=-=========================
|
||||
========^$==========--=-==-=-=--=--=========---=----========-------===--=====----=======--=====--====--=====-=--=-=
|
||||
|
||||
'-' unoccupied cells
|
||||
'=' occupied cells
|
||||
'^' where the hash pointed to in the table initially and linear probing started
|
||||
'$' where linear probing ended because a matching or unoccupied cell
|
||||
was found. This symbol is not shown if the initial guess was correct.
|
||||
|
||||
This example has 244 cells. Each cell uses 8 bytes of local RAM, so just under 2 kB.
|
||||
Each cell represents an allocation in EVE RAM_G. The RAM_G allocation sizes are not
|
||||
represented in this table, except for the overall "113 kB of RAM_G used" message.
|
||||
*/
|
||||
static void ramg_debug(lv_draw_eve_ramg_t * ramg, uint32_t key_hash, uint32_t table_index)
|
||||
{
|
||||
uint32_t table_index_initial_guess = key_hash % ramg->hash_table_cell_count;
|
||||
|
||||
lv_log("%u kB of RAM_G used\n", (unsigned) ramg->ramg_addr_end / 1024);
|
||||
|
||||
for(uint32_t i = 0; i < ramg->hash_table_cell_count; i++) {
|
||||
if(i != 0 && i % 128 == 0) {
|
||||
lv_log("\n");
|
||||
}
|
||||
|
||||
if(i == table_index_initial_guess) {
|
||||
lv_log("^");
|
||||
}
|
||||
else if(i == table_index) {
|
||||
lv_log("$");
|
||||
}
|
||||
else if(ramg->hash_table[i].key) {
|
||||
lv_log("=");
|
||||
}
|
||||
else {
|
||||
lv_log("-");
|
||||
}
|
||||
}
|
||||
|
||||
lv_log("\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif/*LV_USE_EVE_DRAW*/
|
||||
|
||||
48
inc/lvgl/src/draw/eve/lv_draw_eve_ram_g.h
Normal file
48
inc/lvgl/src/draw/eve/lv_draw_eve_ram_g.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file lv_draw_eve_ram_g.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 19 nov 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_EVE_RAM_G_H
|
||||
#define LV_DRAW_EVE_RAM_G_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_DRAW_EVE_RAMG_OUT_OF_RAMG UINT32_MAX
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
bool lv_draw_eve_ramg_get_addr(uint32_t * addr_dst, uintptr_t key,
|
||||
uint32_t addr_size, uint32_t addr_align);
|
||||
|
||||
#endif/*LV_USE_DRAW_EVE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_DRAW_EVE_RAM_G_H */
|
||||
79
inc/lvgl/src/draw/eve/lv_draw_eve_target.h
Normal file
79
inc/lvgl/src/draw/eve/lv_draw_eve_target.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_draw_eve_target.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_EVE_TARGET_H
|
||||
#define LV_DRAW_EVE_TARGET_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include LV_STDBOOL_INCLUDE
|
||||
#include LV_STDINT_INCLUDE
|
||||
|
||||
typedef struct {
|
||||
uint16_t hor_res; /**< active display width */
|
||||
uint16_t ver_res; /**< active display height */
|
||||
uint16_t hcycle; /**< total number of clocks per line, incl front/back porch */
|
||||
uint16_t hoffset; /**< start of active line */
|
||||
uint16_t hsync0; /**< start of horizontal sync pulse */
|
||||
uint16_t hsync1; /**< end of horizontal sync pulse */
|
||||
uint16_t vcycle; /**< total number of lines per screen, including pre/post */
|
||||
uint16_t voffset; /**< start of active screen */
|
||||
uint16_t vsync0; /**< start of vertical sync pulse */
|
||||
uint16_t vsync1; /**< end of vertical sync pulse */
|
||||
uint8_t swizzle; /**< FT8xx output to LCD - pin order */
|
||||
uint8_t pclkpol; /**< LCD data is clocked in on this PCLK edge */
|
||||
uint8_t cspread; /**< helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
|
||||
uint8_t pclk; /**< 60MHz / pclk = pclk frequency */
|
||||
bool has_crystal; /**< has an external clock crystal */
|
||||
bool has_gt911; /**< has a touch controller */
|
||||
uint8_t backlight_pwm; /**< backlight PWM duty cycle 0 = off, 128 = max */
|
||||
uint16_t backlight_freq; /**< backlight PWM frequency. try 4000 if unsure */
|
||||
} lv_draw_eve_parameters_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_EVE_OPERATION_POWERDOWN_SET, /**< set the "PD_N" pin low */
|
||||
LV_DRAW_EVE_OPERATION_POWERDOWN_CLEAR, /**< set the "PD_N" pin high */
|
||||
LV_DRAW_EVE_OPERATION_CS_ASSERT, /**< set the "CS_N" pin low */
|
||||
LV_DRAW_EVE_OPERATION_CS_DEASSERT, /**< set the "CS_N" pin high */
|
||||
LV_DRAW_EVE_OPERATION_SPI_SEND, /**< send `length` bytes of `data` over SPI */
|
||||
LV_DRAW_EVE_OPERATION_SPI_RECEIVE /**< receive `length` bytes into `data` from SPI */
|
||||
} lv_draw_eve_operation_t;
|
||||
|
||||
typedef void (*lv_draw_eve_operation_cb_t)(lv_display_t * disp, lv_draw_eve_operation_t operation, void * data,
|
||||
uint32_t length);
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_EVE_TARGET_H*/
|
||||
127
inc/lvgl/src/draw/eve/lv_draw_eve_triangle.c
Normal file
127
inc/lvgl/src/draw/eve/lv_draw_eve_triangle.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @file lv_draw_eve_triangle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 10 ene 2024
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve_private.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include "../../misc/lv_area_private.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "lv_eve.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_eve_triangle(lv_draw_task_t * t, const lv_draw_triangle_dsc_t * dsc)
|
||||
{
|
||||
|
||||
lv_area_t tri_area;
|
||||
tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
|
||||
bool is_common;
|
||||
lv_area_t draw_area;
|
||||
is_common = lv_area_intersect(&draw_area, &tri_area, &t->clip_area);
|
||||
if(!is_common) return;
|
||||
|
||||
lv_point_t p[3];
|
||||
/*If there is a vertical side use it as p[0] and p[1]*/
|
||||
if(dsc->p[0].x == dsc->p[1].x) {
|
||||
p[0] = lv_point_from_precise(&dsc->p[0]);
|
||||
p[1] = lv_point_from_precise(&dsc->p[1]);
|
||||
p[2] = lv_point_from_precise(&dsc->p[2]);
|
||||
}
|
||||
else if(dsc->p[0].x == dsc->p[2].x) {
|
||||
p[0] = lv_point_from_precise(&dsc->p[0]);
|
||||
p[1] = lv_point_from_precise(&dsc->p[2]);
|
||||
p[2] = lv_point_from_precise(&dsc->p[1]);
|
||||
}
|
||||
else if(dsc->p[1].x == dsc->p[2].x) {
|
||||
p[0] = lv_point_from_precise(&dsc->p[1]);
|
||||
p[1] = lv_point_from_precise(&dsc->p[2]);
|
||||
p[2] = lv_point_from_precise(&dsc->p[0]);
|
||||
}
|
||||
else {
|
||||
p[0] = lv_point_from_precise(&dsc->p[0]);
|
||||
p[1] = lv_point_from_precise(&dsc->p[1]);
|
||||
p[2] = lv_point_from_precise(&dsc->p[2]);
|
||||
|
||||
/*Set the smallest y as p[0]*/
|
||||
if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]);
|
||||
if(p[0].y > p[2].y) lv_point_swap(&p[0], &p[2]);
|
||||
|
||||
/*Set the greatest y as p[1]*/
|
||||
if(p[1].y < p[2].y) lv_point_swap(&p[1], &p[2]);
|
||||
}
|
||||
|
||||
/*Be sure p[0] is on the top*/
|
||||
if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]);
|
||||
|
||||
lv_eve_save_context();
|
||||
|
||||
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
|
||||
|
||||
lv_eve_color(dsc->color);
|
||||
lv_eve_color_opa(dsc->opa);
|
||||
|
||||
lv_eve_color_mask(0, 0, 0, 0);
|
||||
lv_eve_stencil_op(EVE_KEEP, EVE_INVERT);
|
||||
lv_eve_stencil_func(EVE_ALWAYS, 255, 255);
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_EDGE_STRIP_A);
|
||||
|
||||
lv_eve_vertex_2f(p[0].x, p[0].y);
|
||||
lv_eve_vertex_2f(p[1].x, p[1].y);
|
||||
lv_eve_vertex_2f(p[2].x, p[2].y);
|
||||
|
||||
lv_eve_color_mask(1, 1, 1, 1);
|
||||
lv_eve_stencil_func(EVE_EQUAL, 255, 255) ;
|
||||
|
||||
lv_eve_vertex_2f(0, 0);
|
||||
lv_eve_vertex_2f(1022, 0);
|
||||
|
||||
lv_eve_restore_context();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
|
||||
265
inc/lvgl/src/draw/eve/lv_eve.c
Normal file
265
inc/lvgl/src/draw/eve/lv_eve.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @file lv_eve.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 8 jun 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_eve.h"
|
||||
#if LV_USE_DRAW_EVE
|
||||
#include "lv_eve.h"
|
||||
#include "../../libs/FT800-FT813/EVE_commands.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static uint16_t scissor_x1 = 0;
|
||||
static uint16_t scissor_y1 = 0;
|
||||
static uint16_t scissor_x2 = 0;
|
||||
static uint16_t scissor_y2 = 0;
|
||||
|
||||
static lv_eve_drawing_context_t ct = {
|
||||
.primitive = LV_EVE_PRIMITIVE_ZERO_VALUE,
|
||||
.color = {0xff, 0xff, 0xff},
|
||||
.opa = 255,
|
||||
.line_width = 1, /* for format(0) */
|
||||
.point_size = 1,
|
||||
.color_mask = {1, 1, 1, 1},
|
||||
.stencil_func = {EVE_ALWAYS, 0, 255},
|
||||
.stencil_op = {EVE_KEEP, EVE_KEEP},
|
||||
.blend_func = {EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA},
|
||||
.scx = 0,
|
||||
.scy = 0,
|
||||
};
|
||||
|
||||
static lv_eve_drawing_context_t ct_temp;
|
||||
|
||||
static lv_eve_drawing_state_t st;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_eve_save_context(void)
|
||||
{
|
||||
EVE_cmd_dl_burst(DL_SAVE_CONTEXT);
|
||||
ct_temp = ct;
|
||||
}
|
||||
|
||||
void lv_eve_restore_context(void)
|
||||
{
|
||||
EVE_cmd_dl_burst(DL_RESTORE_CONTEXT);
|
||||
ct = ct_temp;
|
||||
}
|
||||
|
||||
|
||||
void lv_eve_primitive(uint8_t context)
|
||||
{
|
||||
if(context != ct.primitive && context != LV_EVE_PRIMITIVE_ZERO_VALUE) {
|
||||
EVE_cmd_dl_burst(DL_BEGIN | context);
|
||||
ct.primitive = context;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_scissor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
|
||||
{
|
||||
if(x1 != scissor_x1 || y1 != scissor_y1) {
|
||||
int16_t adjusted_x1 = x1 > 0 ? x1 - 1 : 0;
|
||||
int16_t adjusted_y1 = y1 > 0 ? y1 - 1 : 0;
|
||||
EVE_cmd_dl_burst(SCISSOR_XY(adjusted_x1, adjusted_y1));
|
||||
scissor_x1 = x1;
|
||||
scissor_y1 = y1;
|
||||
}
|
||||
|
||||
if(x2 != scissor_x2 || y2 != scissor_y2) {
|
||||
uint16_t w = x2 - x1 + 3;
|
||||
uint16_t h = y2 - y1 + 3;
|
||||
EVE_cmd_dl_burst(SCISSOR_SIZE(w, h));
|
||||
scissor_x2 = x2;
|
||||
scissor_y2 = y2;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_color(lv_color_t color)
|
||||
{
|
||||
if((ct.color.red != color.red) || (ct.color.green != color.green) || (ct.color.blue != color.blue)) {
|
||||
EVE_cmd_dl_burst(COLOR_RGB(color.red, color.green, color.blue));
|
||||
ct.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_color_mask(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if((ct.color_mask[0] != r) ||
|
||||
(ct.color_mask[1] != g) ||
|
||||
(ct.color_mask[2] != b) ||
|
||||
(ct.color_mask[3] != a)) {
|
||||
|
||||
EVE_cmd_dl_burst(COLOR_MASK(r, g, b, a));
|
||||
ct.color_mask[0] = r;
|
||||
ct.color_mask[1] = g;
|
||||
ct.color_mask[2] = b;
|
||||
ct.color_mask[3] = a;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_stencil_func(uint8_t func, uint8_t ref, uint8_t mask)
|
||||
{
|
||||
if(func != ct.stencil_func[0] || ref != ct.stencil_func[1] || mask != ct.stencil_func[2]) {
|
||||
|
||||
EVE_cmd_dl_burst(STENCIL_FUNC(func, ref, mask));
|
||||
ct.stencil_func[0] = func;
|
||||
ct.stencil_func[1] = ref;
|
||||
ct.stencil_func[2] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_stencil_op(uint8_t sfail, uint8_t spass)
|
||||
{
|
||||
if(sfail != ct.stencil_op[0] || spass != ct.stencil_op[1]) {
|
||||
EVE_cmd_dl_burst(STENCIL_OP(sfail, spass));
|
||||
ct.stencil_op[0] = sfail;
|
||||
ct.stencil_op[1] = spass;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_blend_func(uint8_t src, uint8_t dst)
|
||||
{
|
||||
if(src != ct.blend_func[0] || dst != ct.blend_func[1]) {
|
||||
EVE_cmd_dl_burst(BLEND_FUNC(src, dst));
|
||||
ct.blend_func[0] = src;
|
||||
ct.blend_func[1] = dst;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_color_opa(lv_opa_t opa)
|
||||
{
|
||||
if(opa != ct.opa) {
|
||||
EVE_cmd_dl_burst(COLOR_A(opa));
|
||||
ct.opa = opa;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_line_width(int32_t width)
|
||||
{
|
||||
if(width != ct.line_width) {
|
||||
EVE_cmd_dl_burst(LINE_WIDTH(width));
|
||||
ct.line_width = width;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_point_size(uint16_t radius)
|
||||
{
|
||||
if(radius != ct.point_size) {
|
||||
EVE_cmd_dl_burst(POINT_SIZE(radius * 16));
|
||||
ct.point_size = radius;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_vertex_2f(int16_t x, int16_t y)
|
||||
{
|
||||
EVE_cmd_dl_burst(VERTEX2F(x, y));
|
||||
}
|
||||
|
||||
void lv_eve_draw_circle_simple(int16_t coord_x1, int16_t coord_y1, uint16_t radius_t)
|
||||
{
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_POINTS);
|
||||
lv_eve_point_size(radius_t);
|
||||
lv_eve_vertex_2f(coord_x1, coord_y1);
|
||||
}
|
||||
|
||||
|
||||
void lv_eve_draw_rect_simple(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, uint16_t radius)
|
||||
{
|
||||
lv_eve_primitive(LV_EVE_PRIMITIVE_RECTS);
|
||||
if(radius > 1) {
|
||||
lv_eve_line_width(radius * 16);
|
||||
}
|
||||
|
||||
lv_eve_vertex_2f(coord_x1 + radius, coord_y1 + radius);
|
||||
lv_eve_vertex_2f(coord_x2 - radius, coord_y2 - radius);
|
||||
}
|
||||
|
||||
void lv_eve_mask_round(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, int16_t radius)
|
||||
{
|
||||
lv_eve_color_mask(0, 0, 0, 1);
|
||||
EVE_cmd_dl_burst(CLEAR(1, 1, 1));
|
||||
|
||||
|
||||
lv_eve_draw_rect_simple(coord_x1, coord_y1, coord_x2, coord_y2, radius);
|
||||
lv_eve_color_mask(1, 1, 1, 0);
|
||||
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
|
||||
}
|
||||
|
||||
void lv_eve_bitmap_source(uint32_t addr)
|
||||
{
|
||||
uint32_t bitmap_source = BITMAP_SOURCE(addr);
|
||||
if(st.bitmap_source != bitmap_source) {
|
||||
EVE_cmd_dl_burst(bitmap_source);
|
||||
st.bitmap_source = bitmap_source;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_bitmap_size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height)
|
||||
{
|
||||
uint32_t bitmap_size = BITMAP_SIZE(filter, wrapx, wrapy, width, height);
|
||||
if(st.bitmap_size != bitmap_size) {
|
||||
EVE_cmd_dl_burst(bitmap_size);
|
||||
st.bitmap_size = bitmap_size;
|
||||
}
|
||||
/* set the high bits too, of the width and height */
|
||||
uint32_t bitmap_size_h = BITMAP_SIZE_H(width, height);
|
||||
if(st.bitmap_size_h != bitmap_size_h) {
|
||||
EVE_cmd_dl_burst(bitmap_size_h);
|
||||
st.bitmap_size_h = bitmap_size_h;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_eve_bitmap_layout(uint8_t format, uint16_t linestride, uint16_t height)
|
||||
{
|
||||
uint32_t bitmap_layout = BITMAP_LAYOUT(format, linestride, height);
|
||||
if(st.bitmap_layout != bitmap_layout) {
|
||||
EVE_cmd_dl_burst(bitmap_layout);
|
||||
st.bitmap_layout = bitmap_layout;
|
||||
}
|
||||
/* set the high bits too, of the linestride and height */
|
||||
uint32_t bitmap_layout_h = BITMAP_LAYOUT_H(linestride, height);
|
||||
if(st.bitmap_layout_h != bitmap_layout_h) {
|
||||
EVE_cmd_dl_burst(bitmap_layout_h);
|
||||
st.bitmap_layout_h = bitmap_layout_h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
151
inc/lvgl/src/draw/eve/lv_eve.h
Normal file
151
inc/lvgl/src/draw/eve/lv_eve.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @file lv_eve.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* Created on: 8 jun 2023
|
||||
* Author: juanj
|
||||
*
|
||||
* Modified by LVGL
|
||||
*/
|
||||
|
||||
#ifndef LV_EVE_H
|
||||
#define LV_EVE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_eve.h"
|
||||
|
||||
#if LV_USE_DRAW_EVE
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../libs/FT800-FT813/EVE.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef enum {
|
||||
LV_EVE_PRIMITIVE_ZERO_VALUE,
|
||||
LV_EVE_PRIMITIVE_BITMAPS = 1UL, /* Bitmap drawing primitive */
|
||||
LV_EVE_PRIMITIVE_POINTS = 2UL, /* Point drawing primitive */
|
||||
LV_EVE_PRIMITIVE_LINES = 3UL, /* Line drawing primitive */
|
||||
LV_EVE_PRIMITIVE_LINE_STRIP = 4UL, /* Line strip drawing primitive */
|
||||
LV_EVE_PRIMITIVE_EDGE_STRIP_R = 5UL, /* Edge strip right side drawing primitive */
|
||||
LV_EVE_PRIMITIVE_EDGE_STRIP_L = 6UL, /* Edge strip left side drawing primitive */
|
||||
LV_EVE_PRIMITIVE_EDGE_STRIP_A = 7UL, /* Edge strip above drawing primitive */
|
||||
LV_EVE_PRIMITIVE_EDGE_STRIP_B = 8UL, /* Edge strip below side drawing primitive */
|
||||
LV_EVE_PRIMITIVE_RECTS = 9UL, /* Rectangle drawing primitive */
|
||||
} lv_eve_primitive_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
lv_eve_primitive_t primitive;
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
int32_t line_width;
|
||||
uint16_t point_size;
|
||||
uint8_t color_mask[4];
|
||||
uint8_t stencil_func[3];
|
||||
uint8_t stencil_op[2];
|
||||
uint8_t blend_func[2];
|
||||
uint16_t scx;
|
||||
uint16_t scy;
|
||||
} lv_eve_drawing_context_t;
|
||||
|
||||
/* drawing context that is not saved and restored
|
||||
* by SAVE_CONTEXT and RESTORE_CONTEXT
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t bitmap_source;
|
||||
uint32_t bitmap_size;
|
||||
uint32_t bitmap_size_h;
|
||||
uint32_t bitmap_layout;
|
||||
uint32_t bitmap_layout_h;
|
||||
} lv_eve_drawing_state_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_eve_save_context(void);
|
||||
void lv_eve_restore_context(void);
|
||||
void lv_eve_scissor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
|
||||
void lv_eve_primitive(uint8_t context);
|
||||
void lv_eve_color(lv_color_t color);
|
||||
void lv_eve_color_opa(lv_opa_t opa);
|
||||
void lv_eve_line_width(int32_t width);
|
||||
void lv_eve_point_size(uint16_t radius);
|
||||
void lv_eve_vertex_2f(int16_t x, int16_t y);
|
||||
void lv_eve_color_mask(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
void lv_eve_stencil_func(uint8_t func, uint8_t ref, uint8_t mask);
|
||||
void lv_eve_stencil_op(uint8_t sfail, uint8_t spass);
|
||||
void lv_eve_blend_func(uint8_t src, uint8_t dst);
|
||||
|
||||
void lv_eve_draw_circle_simple(int16_t coord_x1, int16_t coord_y1, uint16_t radius_t);
|
||||
void lv_eve_draw_rect_simple(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2,
|
||||
uint16_t radius);
|
||||
void lv_eve_mask_round(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, int16_t radius);
|
||||
|
||||
/**
|
||||
* Set the bitmap source to `addr`. SPI transmission will occur unless it is already set to this value.
|
||||
* The bitmap source is not part of the saved and restored context.
|
||||
* @param addr the remote EVE memory address to set as the bitmap source
|
||||
*/
|
||||
void lv_eve_bitmap_source(uint32_t addr);
|
||||
|
||||
/**
|
||||
* Set the bitmap size and sampling parameters. SPI transmission will occur unless the currently set parameters are already these.
|
||||
* The bitmap size is not part of the saved and restored context.
|
||||
* @param filter the sampling method. Either EVE_NEAREST or EVE_BILINEAR
|
||||
* @param wrapx the out of bounds sampling behavior in the X direction. Either EVE_BORDER or EVE_REPEAT
|
||||
* @param wrapy the out of bounds sampling behavior in the Y direction. Either EVE_BORDER or EVE_REPEAT
|
||||
* @param width the width of the bitmap in pixels
|
||||
* @param height the height of the bitmap in pixels
|
||||
*/
|
||||
void lv_eve_bitmap_size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height);
|
||||
|
||||
/**
|
||||
* Set the bitmap format/layout parameters. SPI transmission will occur unless the currently set parameters are already these.
|
||||
* The bitmap layout is not part of the saved and restored context.
|
||||
* @param format an eve color format value like EVE_RGB565
|
||||
* @param linestride the stride of the bitmap rows in bytes
|
||||
* @param height the number of rows in the bitmap
|
||||
*/
|
||||
void lv_eve_bitmap_layout(uint8_t format, uint16_t linestride, uint16_t height);
|
||||
|
||||
/**********************
|
||||
* EXTERN VARIABLES
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* INLINE FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_EVE*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_EVE_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user