打包keil_MDK的工程

This commit is contained in:
不吃油炸鸡
2026-02-26 11:25:38 +08:00
parent ef38c0f19f
commit aae7ce5938
1200 changed files with 0 additions and 832317 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
/**
* @file lv_version.h
* The current version of LVGL
*/
#ifndef LVGL_VERSION_H
#define LVGL_VERSION_H
#define LVGL_VERSION_MAJOR 9
#define LVGL_VERSION_MINOR 2
#define LVGL_VERSION_PATCH 3
#define LVGL_VERSION_INFO "dev"
#endif /* LVGL_VERSION_H */

View File

@@ -1,194 +0,0 @@
/**
* @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/tick/lv_tick.h"
#include "src/core/lv_obj.h"
#include "src/core/lv_group.h"
#include "src/indev/lv_indev.h"
#include "src/core/lv_refr.h"
#include "src/display/lv_display.h"
#include "src/font/lv_font.h"
#include "src/font/lv_binfont_loader.h"
#include "src/font/lv_font_fmt_txt.h"
#include "src/widgets/animimage/lv_animimage.h"
#include "src/widgets/arc/lv_arc.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/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/others/snapshot/lv_snapshot.h"
#include "src/others/sysmon/lv_sysmon.h"
#include "src/others/monkey/lv_monkey.h"
#include "src/others/gridnav/lv_gridnav.h"
#include "src/others/fragment/lv_fragment.h"
#include "src/others/imgfont/lv_imgfont.h"
#include "src/others/observer/lv_observer.h"
#include "src/others/ime/lv_ime_pinyin.h"
#include "src/others/file_explorer/lv_file_explorer.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/gif/lv_gif.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/layouts/lv_layout.h"
#include "src/draw/lv_draw.h"
#include "src/draw/lv_draw_buf.h"
#include "src/draw/lv_draw_vector.h"
#include "src/draw/sw/lv_draw_sw.h"
#include "src/themes/lv_theme.h"
#include "src/drivers/lv_drivers.h"
#include "src/lv_api_map_v8.h"
#include "src/lv_api_map_v9_0.h"
#include "src/lv_api_map_v9_1.h"
#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*/

View File

@@ -1,169 +0,0 @@
/**
* @file lv_port_disp_templ.c
*
*/
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1
/*********************
* INCLUDES
*********************/
#include "lv_port_disp.h"
#include <stdbool.h>
// lcd
#include "lcd.h"
#include "lcd_init.h"
/*********************
* DEFINES
*********************/
#ifndef MY_DISP_HOR_RES
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
#define MY_DISP_HOR_RES 240
#endif
#ifndef MY_DISP_VER_RES
#warning Please define or replace the macro MY_DISP_VER_RES with the actual screen height, default value 240 is used for now.
#define MY_DISP_VER_RES 240
#endif
#define BYTE_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) /*will be 2 for RGB565 */
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void disp_init(void);
static void disp_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
/**********************
* STATIC VARIABLES
**********************/
// 1. 定义一个静态变量来保存当前的 driver 句柄
static lv_display_t *g_current_disp_drv = NULL;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_port_disp_init(void)
{
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
/*------------------------------------
* Create a display and set a flush_cb
* -----------------------------------*/
lv_display_t * disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
lv_display_set_flush_cb(disp, disp_flush);
g_current_disp_drv = disp;
#define BUFFER_METHOD 1
#if BUFFER_METHOD == 1
/* Example 1
* One buffer for partial rendering*/
LV_ATTRIBUTE_MEM_ALIGN
static uint8_t buf_1_1[MY_DISP_HOR_RES * MY_DISP_VER_RES / 4 * BYTE_PER_PIXEL];
lv_display_set_buffers(disp, buf_1_1, NULL, sizeof(buf_1_1), LV_DISPLAY_RENDER_MODE_PARTIAL);
#elif BUFFER_METHOD == 2
/* Example 2
* Two buffers for partial rendering
* In flush_cb DMA or similar hardware should be used to update the display in the background.*/
LV_ATTRIBUTE_MEM_ALIGN
static uint8_t buf_2_1[MY_DISP_HOR_RES * MY_DISP_VER_RES / 8 * BYTE_PER_PIXEL];
LV_ATTRIBUTE_MEM_ALIGN
static uint8_t buf_2_2[MY_DISP_HOR_RES * MY_DISP_VER_RES / 8 * BYTE_PER_PIXEL];
lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1), LV_DISPLAY_RENDER_MODE_PARTIAL);
#elif BUFFER_METHOD == 3
/* Example 3
* Two buffers screen sized buffer for double buffering.
* Both LV_DISPLAY_RENDER_MODE_DIRECT and LV_DISPLAY_RENDER_MODE_FULL works, see their comments*/
LV_ATTRIBUTE_MEM_ALIGN
static uint8_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES * BYTE_PER_PIXEL];
LV_ATTRIBUTE_MEM_ALIGN
static uint8_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES * BYTE_PER_PIXEL];
lv_display_set_buffers(disp, buf_3_1, buf_3_2, sizeof(buf_3_1), LV_DISPLAY_RENDER_MODE_DIRECT);
#endif
}
/**********************
* STATIC FUNCTIONS
**********************/
void lcd_flush_ready_callback(void)
{
if (g_current_disp_drv != NULL) {
lv_display_flush_ready(g_current_disp_drv);
}
}
/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
/*You code here*/
LCD_Init();
LCD_Fill(0,0, LCD_W, LCD_H, BLACK);
LCD_Close_Light();
LCD_Set_Flush_Complete_Callback(lcd_flush_ready_callback);
}
volatile bool disp_flush_enabled = true;
/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_enable_update(void)
{
disp_flush_enabled = true;
}
/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_disable_update(void)
{
disp_flush_enabled = false;
}
/*Flush the content of the internal buffer the specific area on the display.
*`px_map` contains the rendered image as raw pixel map and it should be copied to `area` on the display.
*You can use DMA or any hardware acceleration to do this operation in the background but
*'lv_display_flush_ready()' has to be called when it's finished.*/
static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
{
static lv_display_rotation_t last_rotation = LV_DISPLAY_ROTATION_0;
lv_display_rotation_t current_rotation = lv_display_get_rotation(disp_drv);
lv_area_t rotated_area;
if (current_rotation != last_rotation) {
LCD_SetRotation(current_rotation * 90); // 仅在旋转状态改变时调用
last_rotation = current_rotation; // 更新上次状态
}
if(disp_flush_enabled) {
LCD_Color_Render_Async(area->x1,area->y1,area->x2,area->y2, (uint16_t *)px_map);
}
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing*/
// lv_display_flush_ready(disp_drv);
}
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

View File

@@ -1,58 +0,0 @@
/**
* @file lv_port_disp_templ.h
*
*/
/*Copy this file as "lv_port_disp.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_DISP_TEMPL_H
#define LV_PORT_DISP_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
// #include "lvgl/lvgl.h"
#include "lvgl.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/* Initialize low level display driver */
void lv_port_disp_init(void);
/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_enable_update(void);
/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_disable_update(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_DISP_TEMPL_H*/
#endif /*Disable/Enable content*/

View File

@@ -1,266 +0,0 @@
/**
* @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.h"
#include "../others/sysmon/lv_sysmon.h"
#include "../stdlib/builtin/lv_tlsf.h"
#if LV_USE_FONT_COMPRESSED
#include "../font/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 "../others/sysmon/lv_sysmon_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 {
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;
lv_cache_t * img_cache;
lv_cache_t * img_header_cache;
lv_draw_global_info_t draw_info;
#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_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_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 != 0
lv_style_t fe_list_button_style;
#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_NUTTX
struct lv_nuttx_ctx_t * nuttx_ctx;
#endif
#if LV_USE_OS != LV_OS_NONE
lv_mutex_t lv_general_mutex;
#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
void * user_data;
} 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*/

View File

@@ -1,530 +0,0 @@
/**
* @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;
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);
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;
}
/**********************
* 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;
}

View File

@@ -1,245 +0,0 @@
/**
* @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 focused object 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 a new object group
* @return pointer to the new object group
*/
lv_group_t * lv_group_create(void);
/**
* Delete a group object
* @param group pointer to a group
*/
void lv_group_delete(lv_group_t * group);
/**
* Set a default group. New object are 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 the default group
* @return pointer to the default group
*/
lv_group_t * lv_group_get_default(void);
/**
* Add an object to a group
* @param group pointer to a group
* @param obj pointer to an object to add
*/
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj);
/**
* Swap 2 object in a group. The object must be in the same group
* @param obj1 pointer to an object
* @param obj2 pointer to another object
*/
void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2);
/**
* Remove an object from its group
* @param obj pointer to an object to remove
*/
void lv_group_remove_obj(lv_obj_t * obj);
/**
* Remove all objects from a group
* @param group pointer to a group
*/
void lv_group_remove_all_objs(lv_group_t * group);
/**
* Focus on an object (defocus the current)
* @param obj pointer to an object to focus on
*/
void lv_group_focus_obj(lv_obj_t * obj);
/**
* Focus the next object in a group (defocus the current)
* @param group pointer to a group
*/
void lv_group_focus_next(lv_group_t * group);
/**
* Focus the previous object in a group (defocus the current)
* @param group pointer to a group
*/
void lv_group_focus_prev(lv_group_t * group);
/**
* Do not let to change the focus from the current object
* @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 the focuses object of a group
* @param group pointer to a group
* @param c a character (use LV_KEY_.. to navigate)
* @return result of focused object 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 object is focused
* @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 item in a group is focused if the currently focused obj 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 focus next/prev will allow wrapping from first->last or last->first object.
* @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 the focused object or NULL if there isn't one
* @param group pointer to a group
* @return pointer to the focused object
*/
lv_obj_t * lv_group_get_focused(const lv_group_t * group);
/**
* Get the 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 the edge callback function of a group
* @param group pointer to a group
* @return the call back function or NULL if not set
*/
lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group);
/**
* Get the current mode (edit or navigate).
* @param group pointer to group
* @return true: edit mode; false: navigate mode
*/
bool lv_group_get_editing(const lv_group_t * group);
/**
* Get whether focus next/prev will allow wrapping from first->last or last->first object.
* @param group pointer to group
*/
bool lv_group_get_wrap(lv_group_t * group);
/**
* Get the number of object in the group
* @param group pointer to a group
* @return number of objects in the group
*/
uint32_t lv_group_get_obj_count(lv_group_t * group);
/**
* Get the nth object within a group
* @param group pointer to a group
* @param index index of object within the group
* @return pointer to the object
*/
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);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GROUP_H*/

View File

@@ -1,75 +0,0 @@
/**
* @file lv_group_private.h
*
*/
#ifndef LV_GROUP_PRIVATE_H
#define LV_GROUP_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#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 {
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*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,486 +0,0 @@
/**
* @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
**********************/
/**
* Possible states of a widget.
* OR-ed values are possible
*/
enum {
LV_STATE_DEFAULT = 0x0000,
LV_STATE_CHECKED = 0x0001,
LV_STATE_FOCUSED = 0x0002,
LV_STATE_FOCUS_KEY = 0x0004,
LV_STATE_EDITED = 0x0008,
LV_STATE_HOVERED = 0x0010,
LV_STATE_PRESSED = 0x0020,
LV_STATE_SCROLLED = 0x0040,
LV_STATE_DISABLED = 0x0080,
LV_STATE_USER_1 = 0x1000,
LV_STATE_USER_2 = 0x2000,
LV_STATE_USER_3 = 0x4000,
LV_STATE_USER_4 = 0x8000,
LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/
};
/**
* 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
*/
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*/
};
/**
* 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 = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/
LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/
LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/
LV_OBJ_FLAG_CHECKABLE = (1L << 3), /**< Toggle checked state when the object is clicked*/
LV_OBJ_FLAG_SCROLLABLE = (1L << 4), /**< Make the object scrollable*/
LV_OBJ_FLAG_SCROLL_ELASTIC = (1L << 5), /**< Allow scrolling inside but with slower speed*/
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6), /**< Make the object scroll further when "thrown"*/
LV_OBJ_FLAG_SCROLL_ONE = (1L << 7), /**< Allow scrolling only one snappable children*/
LV_OBJ_FLAG_SCROLL_CHAIN_HOR = (1L << 8), /**< Allow propagating the horizontal scroll to a parent*/
LV_OBJ_FLAG_SCROLL_CHAIN_VER = (1L << 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 = (1L << 10), /**< Automatically scroll object to make it visible when focused*/
LV_OBJ_FLAG_SCROLL_WITH_ARROW = (1L << 11), /**< Allow scrolling the focused object with arrow keys*/
LV_OBJ_FLAG_SNAPPABLE = (1L << 12), /**< If scroll snap is enabled on the parent it can snap to this object*/
LV_OBJ_FLAG_PRESS_LOCK = (1L << 13), /**< Keep the object pressed even if the press slid from the object*/
LV_OBJ_FLAG_EVENT_BUBBLE = (1L << 14), /**< Propagate the events to the parent too*/
LV_OBJ_FLAG_GESTURE_BUBBLE = (1L << 15), /**< Propagate the gestures to the parent*/
LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object not positioned by the layouts*/
LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS = (1L << 19), /**< Send `LV_EVENT_DRAW_TASK_ADDED` events*/
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 20),/**< Do not clip the children to the parent's ext draw size*/
#if LV_USE_FLEX
LV_OBJ_FLAG_FLEX_IN_NEW_TRACK = (1L << 21), /**< Start a new flex track on this item*/
#endif
LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/
LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/
LV_OBJ_FLAG_USER_1 = (1L << 27), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/
LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/
} lv_obj_flag_t;
#if LV_USE_OBJ_PROPERTY
enum {
/*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_FLEX_IN_NEW_TRACK, LV_PROPERTY_TYPE_INT, 21),
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_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_CHECKED, LV_PROPERTY_TYPE_INT, 31),
LV_PROPERTY_ID(OBJ, STATE_FOCUSED, LV_PROPERTY_TYPE_INT, 32),
LV_PROPERTY_ID(OBJ, STATE_FOCUS_KEY, LV_PROPERTY_TYPE_INT, 33),
LV_PROPERTY_ID(OBJ, STATE_EDITED, LV_PROPERTY_TYPE_INT, 34),
LV_PROPERTY_ID(OBJ, STATE_HOVERED, LV_PROPERTY_TYPE_INT, 35),
LV_PROPERTY_ID(OBJ, STATE_PRESSED, LV_PROPERTY_TYPE_INT, 36),
LV_PROPERTY_ID(OBJ, STATE_SCROLLED, LV_PROPERTY_TYPE_INT, 37),
LV_PROPERTY_ID(OBJ, STATE_DISABLED, LV_PROPERTY_TYPE_INT, 38),
/*not used bit8-bit11*/
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_INT, 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_update_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);
/*=======================
* 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 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);
#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);
/**
* 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_get_child_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) do{}while(0)
#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*/

View File

@@ -1,204 +0,0 @@
/**
* @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(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;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
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;
}

View File

@@ -1,72 +0,0 @@
/**
* @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);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_CLASS_H*/

View File

@@ -1,78 +0,0 @@
/**
* @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*/

View File

@@ -1,326 +0,0 @@
/**
* @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"
#include "../draw/lv_draw_arc.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS (&lv_obj_class)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* 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)
{
draw_dsc->base.obj = obj;
draw_dsc->base.part = part;
lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part);
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;
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) {
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
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 = lv_obj_get_style_bg_color_filtered(obj, part);
draw_dsc->bg_grad.stops[1].color = lv_obj_get_style_bg_grad_color_filtered(obj, part);
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);
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
}
}
}
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);
draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
}
}
}
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);
draw_dsc->bg_image_recolor = lv_obj_get_style_text_color_filtered(obj, part);
}
else {
draw_dsc->bg_image_recolor = lv_obj_get_style_bg_image_recolor_filtered(obj, part);
draw_dsc->bg_image_recolor_opa = lv_obj_get_style_bg_image_recolor_opa(obj, part);
draw_dsc->bg_image_tiled = lv_obj_get_style_bg_image_tiled(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);
draw_dsc->shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part);
}
}
}
}
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);
}
}
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_label_dsc_t * draw_dsc)
{
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) return;
lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part);
if(opa < LV_OPA_MAX) {
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
}
if(draw_dsc->opa <= LV_OPA_MIN) return;
draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part);
draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part);
draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part);
draw_dsc->decor = lv_obj_get_style_text_decor(obj, part);
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(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);
}
void lv_obj_init_draw_image_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_image_dsc_t * draw_dsc)
{
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) return;
lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part);
if(opa < LV_OPA_MAX) {
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
}
if(draw_dsc->opa <= LV_OPA_MIN) 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;
draw_dsc->recolor_opa = lv_obj_get_style_image_recolor_opa(obj, part);
draw_dsc->recolor = lv_obj_get_style_image_recolor_filtered(obj, part);
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
}
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_line_dsc_t * draw_dsc)
{
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) return;
lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part);
if(opa < LV_OPA_MAX) {
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
}
if(draw_dsc->opa <= LV_OPA_MIN) return;
draw_dsc->width = lv_obj_get_style_line_width(obj, part);
if(draw_dsc->width == 0) return;
draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part);
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;
if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
}
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, lv_part_t part, lv_draw_arc_dsc_t * draw_dsc)
{
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) return;
draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part);
if(draw_dsc->opa <= LV_OPA_MIN) return;
lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part);
if(opa < LV_OPA_MAX) {
draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa);
}
if(draw_dsc->opa <= LV_OPA_MIN) return;
draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part);
draw_dsc->img_src = lv_obj_get_style_arc_image_src(obj, part);
draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
}
int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, lv_part_t part)
{
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 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;
return s;
}
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
{
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);
}
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
**********************/

View File

@@ -1,113 +0,0 @@
/**
* @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"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_LAYER_TYPE_NONE,
LV_LAYER_TYPE_SIMPLE,
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);
/**
* 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*/

View File

@@ -1,48 +0,0 @@
/**
* @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*/

View File

@@ -1,419 +0,0 @@
/**
* @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 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;
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;
base->event_cb(base, e);
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_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 i;
for(i = 0; i < event_cnt; i++) {
lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i);
if(dsc->cb == event_cb) {
lv_obj_remove_event(obj, i);
return true;
}
}
return false;
}
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_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;
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 && 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;
}
}
/**********************
* 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);
/*Call the input device's feedback callback if set*/
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 || e->stop_processing || e->stop_bubbling) return res;
}
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;
}
}

View File

@@ -1,198 +0,0 @@
/**
* @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"
/*********************
* 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_cb(lv_obj_t * obj, lv_event_cb_t event_cb);
bool lv_obj_remove_event_dsc(lv_obj_t * obj, lv_event_dsc_t * dsc);
/**
* 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);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_EVENT_H*/

View File

@@ -1,62 +0,0 @@
/**
* @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*/

View File

@@ -1,122 +0,0 @@
/**
* @file lv_obj_id.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_obj_class_private.h"
#include "lv_obj_private.h"
#include "lv_global.h"
#include "../osal/lv_os.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)
{
LV_UNUSED(obj);
obj->id = NULL;
}
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len)
{
const char * name;
if(obj == NULL || obj->class_p == NULL) return NULL;
if(buf == NULL) return NULL;
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*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,451 +0,0 @@
/**
* @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 needs 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 children 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);
/**
* 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 objects
* @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 objects
* @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);
/**
* 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);
/**
* 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
*/
void 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
*/
void 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);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_POS_H*/

View File

@@ -1,88 +0,0 @@
/**
* @file lv_obj_private.h
*
*/
#ifndef LV_OBJ_PRIVATE_H
#define LV_OBJ_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#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;
lv_event_list_t event_list;
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 */
};
struct lv_obj_t {
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;
lv_state_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 is_deleting : 1;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_PRIVATE_H*/

View File

@@ -1,302 +0,0 @@
/**
* @file lv_obj_id.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
*********************/
/**********************
* TYPEDEFS
**********************/
typedef void (*lv_property_set_int_t)(lv_obj_t *, int32_t);
typedef void (*lv_property_set_bool_t)(lv_obj_t *, bool);
typedef void (*lv_property_set_precise_t)(lv_obj_t *, lv_value_precise_t);
typedef void (*lv_property_set_color_t)(lv_obj_t *, lv_color_t);
typedef void (*lv_property_set_point_t)(lv_obj_t *, lv_point_t *);
typedef void (*lv_property_set_pointer_t)(lv_obj_t *, const void *);
typedef lv_result_t (*lv_property_setter_t)(lv_obj_t *, lv_prop_id_t, const lv_property_t *);
typedef int32_t (*lv_property_get_int_t)(const lv_obj_t *);
typedef bool (*lv_property_get_bool_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 lv_point_t (*lv_property_get_point_t)(lv_obj_t *);
typedef void * (*lv_property_get_pointer_t)(const 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) {
lv_obj_get_local_style_prop(obj, index, &value.style, 0);
value.id = id;
value.selector = 0;
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, uint32_t selector)
{
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;
}
lv_obj_get_local_style_prop(obj, id, &value.style, selector);
value.id = id;
value.selector = selector;
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: {
if(set)((lv_property_set_int_t)(prop->setter))(obj, value->num);
else value->num = ((lv_property_get_int_t)(prop->getter))(obj);
break;
}
case LV_PROPERTY_TYPE_BOOL: {
if(set)((lv_property_set_bool_t)(prop->setter))(obj, value->enable);
else value->enable = ((lv_property_get_bool_t)(prop->getter))(obj);
break;
}
case LV_PROPERTY_TYPE_PRECISE: {
if(set)((lv_property_set_precise_t)(prop->setter))(obj, value->precise);
else value->precise = ((lv_property_get_precise_t)(prop->getter))(obj);
break;
}
case LV_PROPERTY_TYPE_COLOR: {
if(set)((lv_property_set_color_t)prop->setter)(obj, value->color);
else value->color = ((lv_property_get_color_t)(prop->getter))(obj);
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;
}
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: {
if(set)((lv_property_set_pointer_t)(prop->setter))(obj, value->ptr);
else value->ptr = ((lv_property_get_pointer_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*/

View File

@@ -1,209 +0,0 @@
/**
* @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"
#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_ID(clz, name, type, index) LV_PROPERTY_## clz ##_##name = (LV_PROPERTY_## clz ##_START + (index)) | ((type) << LV_PROPERTY_TYPE_SHIFT)
#define LV_PROPERTY_ID_TYPE(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, sizeof(array)/sizeof(array[0]))
/**********************
* TYPEDEFS
**********************/
/**
* Group of predefined widget ID start value.
*/
enum {
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 */
/*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; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/
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*/
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 */
};
};
} 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 an object
* @param value The property value to set
* @return return LV_RESULT_OK if success
*/
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 an object
* @param value The property value array to set
* @param count The count of the property value array
* @return return LV_RESULT_OK if success
*/
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 object.
* If id is a style property, the style selector is default to 0.
* @param obj pointer to an object
* @param id ID of which property to read
* @return return the property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if failed.
*/
lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id);
/**
* Read a style property value from object
* @param obj pointer to an object
* @param id ID of style property
* @param selector selector for the style property.
* @return return the property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if failed.
*/
lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_t selector);
/**
* Get the property ID by name recursively to base classes. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`.
* @param obj pointer to an object that has specified property or base class has.
* @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 the property ID by name without check base class recursively. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`.
* @param clz pointer to an object class that has specified property or base class has.
* @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 the style property ID by name. Requires to enable `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"
#endif /*LV_USE_OBJ_PROPERTY*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_PROPERTY_H*/

View File

@@ -1,799 +0,0 @@
/**
* @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)
#define SCROLL_ANIM_TIME_MIN 200 /*ms*/
#define SCROLL_ANIM_TIME_MAX 400 /*ms*/
#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(lv_obj_t * obj)
{
if(obj->spec_attr == NULL) return 0;
return -obj->spec_attr->scroll.y;
}
int32_t lv_obj_get_scroll_bottom(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++) {
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(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++) {
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(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++) {
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_ANIM_ON) {
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);
}
return false;
}
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 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(sb_h, SCROLLBAR_MIN_SIZE);
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(sb_w, SCROLLBAR_MIN_SIZE);
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 == LV_ANIM_OFF ? 0 : x_scroll;
scroll_value->y += anim_en == LV_ANIM_OFF ? 0 : y_scroll;
lv_obj_scroll_by(parent, x_scroll, y_scroll, anim_en);
}

View File

@@ -1,290 +0,0 @@
/**
* @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 object 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 an object
* @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 the object in which directions can be scrolled
* @param obj pointer to an object
* @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t`
*/
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 an object
* @param align the snap align to set from `lv_scroll_snap_t`
*/
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 an object
* @param align the snap align to set from `lv_scroll_snap_t`
*/
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 an object
* @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 the object in which directions can be scrolled
* @param obj pointer to an object
*/
lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj);
/**
* Get where to snap the children when scrolling ends horizontally
* @param obj pointer to an object
* @return the current snap align from `lv_scroll_snap_t`
*/
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj);
/**
* Get where to snap the children when scrolling ends vertically
* @param obj pointer to an object
* @return the current snap align 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.
* @param obj pointer to an object
* @return the current scroll position from the left edge.
* If the object is not scrolled return 0
* If scrolled return > 0
* If scrolled in (elastic scroll) return < 0
*/
int32_t lv_obj_get_scroll_x(const lv_obj_t * obj);
/**
* Get current Y scroll position.
* @param obj pointer to an object
* @return the current scroll position from the top edge.
* If the object is not scrolled return 0
* If scrolled return > 0
* If scrolled inside return < 0
*/
int32_t lv_obj_get_scroll_y(const lv_obj_t * obj);
/**
* Return the height of the area above the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area above the object in pixels
*/
int32_t lv_obj_get_scroll_top(lv_obj_t * obj);
/**
* Return the height of the area below the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area below the object in pixels
*/
int32_t lv_obj_get_scroll_bottom(lv_obj_t * obj);
/**
* Return the width of the area on the left the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area on the left the object in pixels
*/
int32_t lv_obj_get_scroll_left(lv_obj_t * obj);
/**
* Return the width of the area on the right the object.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj pointer to an object
* @return the scrollable area on the right the object in pixels
*/
int32_t lv_obj_get_scroll_right(lv_obj_t * obj);
/**
* Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress.
* If no scrolling animation, give the current `x` or `y` scroll position.
* @param obj pointer to an object
* @param end pointer to store the result
*/
void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end);
/*=====================
* Other functions
*====================*/
/**
* Scroll by a given amount of pixels
* @param obj pointer to an object 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
* @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 x, int32_t y, lv_anim_enable_t anim_en);
/**
* Scroll by a given amount of pixels.
* `dx` and `dy` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object 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 a given coordinate on an object.
* `x` and `y` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object 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 a given X coordinate on an object.
* `x` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object 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 a given Y coordinate on an object
* `y` will be limited internally to allow scrolling only on the content area.
* @param obj pointer to an object 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 to an object until it becomes visible on its parent
* @param obj pointer to an object 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 to an object until it becomes visible on its parent.
* Do the same on the parent's parent, and so on.
* Therefore the object will be scrolled into view even it has nested scrollable parents
* @param obj pointer to an object 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 an object is being scrolled or not at this moment
* @param obj pointer to an object
* @return true: `obj` is being scrolled
*/
bool lv_obj_is_scrolling(const lv_obj_t * obj);
/**
* Check the children of `obj` and scroll `obj` to fulfill the scroll_snap settings
* @param obj an object whose children needs to 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 an object
* @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 an object
*/
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 an object
* @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*/

View File

@@ -1,50 +0,0 @@
/**
* @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*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,318 +0,0 @@
/**
* @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
**********************/
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;
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 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);
/**
* 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 selector & 0xFFFF;
}
static inline lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
{
return 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);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_OBJ_STYLE_H*/

View File

@@ -1,897 +0,0 @@
/*
**********************************************************************
* DO NOT EDIT
* This file is automatically generated by "style_api_gen.py"
**********************************************************************
*/
#include "lv_obj.h"
void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_WIDTH, v, selector);
}
void lv_obj_set_style_min_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_WIDTH, v, selector);
}
void lv_obj_set_style_max_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_WIDTH, v, selector);
}
void lv_obj_set_style_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_HEIGHT, v, selector);
}
void lv_obj_set_style_min_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_HEIGHT, v, selector);
}
void lv_obj_set_style_max_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_HEIGHT, v, selector);
}
void lv_obj_set_style_length(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LENGTH, v, selector);
}
void lv_obj_set_style_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_X, v, selector);
}
void lv_obj_set_style_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_Y, v, selector);
}
void lv_obj_set_style_align(lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ALIGN, v, selector);
}
void lv_obj_set_style_transform_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_WIDTH, v, selector);
}
void lv_obj_set_style_transform_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_HEIGHT, v, selector);
}
void lv_obj_set_style_translate_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_X, v, selector);
}
void lv_obj_set_style_translate_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_Y, v, selector);
}
void lv_obj_set_style_transform_scale_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SCALE_X, v, selector);
}
void lv_obj_set_style_transform_scale_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SCALE_Y, v, selector);
}
void lv_obj_set_style_transform_rotation(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ROTATION, v, selector);
}
void lv_obj_set_style_transform_pivot_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_X, v, selector);
}
void lv_obj_set_style_transform_pivot_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_Y, v, selector);
}
void lv_obj_set_style_transform_skew_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SKEW_X, v, selector);
}
void lv_obj_set_style_transform_skew_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SKEW_Y, v, selector);
}
void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_TOP, v, selector);
}
void lv_obj_set_style_pad_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_BOTTOM, v, selector);
}
void lv_obj_set_style_pad_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_LEFT, v, selector);
}
void lv_obj_set_style_pad_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_RIGHT, v, selector);
}
void lv_obj_set_style_pad_row(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_ROW, v, selector);
}
void lv_obj_set_style_pad_column(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector);
}
void lv_obj_set_style_margin_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_TOP, v, selector);
}
void lv_obj_set_style_margin_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_BOTTOM, v, selector);
}
void lv_obj_set_style_margin_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_LEFT, v, selector);
}
void lv_obj_set_style_margin_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_RIGHT, v, selector);
}
void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector);
}
void lv_obj_set_style_bg_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_OPA, v, selector);
}
void lv_obj_set_style_bg_grad_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector);
}
void lv_obj_set_style_bg_grad_dir(lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_DIR, v, selector);
}
void lv_obj_set_style_bg_main_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_STOP, v, selector);
}
void lv_obj_set_style_bg_grad_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_STOP, v, selector);
}
void lv_obj_set_style_bg_main_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_OPA, v, selector);
}
void lv_obj_set_style_bg_grad_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_OPA, v, selector);
}
void lv_obj_set_style_bg_grad(lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD, v, selector);
}
void lv_obj_set_style_bg_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_SRC, v, selector);
}
void lv_obj_set_style_bg_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_OPA, v, selector);
}
void lv_obj_set_style_bg_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_RECOLOR, v, selector);
}
void lv_obj_set_style_bg_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_RECOLOR_OPA, v, selector);
}
void lv_obj_set_style_bg_image_tiled(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_TILED, v, selector);
}
void lv_obj_set_style_border_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector);
}
void lv_obj_set_style_border_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_OPA, v, selector);
}
void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_WIDTH, v, selector);
}
void lv_obj_set_style_border_side(lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_SIDE, v, selector);
}
void lv_obj_set_style_border_post(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_POST, v, selector);
}
void lv_obj_set_style_outline_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_WIDTH, v, selector);
}
void lv_obj_set_style_outline_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector);
}
void lv_obj_set_style_outline_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_OPA, v, selector);
}
void lv_obj_set_style_outline_pad(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_PAD, v, selector);
}
void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_WIDTH, v, selector);
}
void lv_obj_set_style_shadow_offset_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFFSET_X, v, selector);
}
void lv_obj_set_style_shadow_offset_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFFSET_Y, v, selector);
}
void lv_obj_set_style_shadow_spread(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_SPREAD, v, selector);
}
void lv_obj_set_style_shadow_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector);
}
void lv_obj_set_style_shadow_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OPA, v, selector);
}
void lv_obj_set_style_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_OPA, v, selector);
}
void lv_obj_set_style_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_RECOLOR, v, selector);
}
void lv_obj_set_style_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_RECOLOR_OPA, v, selector);
}
void lv_obj_set_style_line_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_WIDTH, v, selector);
}
void lv_obj_set_style_line_dash_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_WIDTH, v, selector);
}
void lv_obj_set_style_line_dash_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector);
}
void lv_obj_set_style_line_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_ROUNDED, v, selector);
}
void lv_obj_set_style_line_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector);
}
void lv_obj_set_style_line_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_OPA, v, selector);
}
void lv_obj_set_style_arc_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector);
}
void lv_obj_set_style_arc_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_ROUNDED, v, selector);
}
void lv_obj_set_style_arc_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector);
}
void lv_obj_set_style_arc_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_OPA, v, selector);
}
void lv_obj_set_style_arc_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_IMAGE_SRC, v, selector);
}
void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.color = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector);
}
void lv_obj_set_style_text_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OPA, v, selector);
}
void lv_obj_set_style_text_font(lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_FONT, v, selector);
}
void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LETTER_SPACE, v, selector);
}
void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LINE_SPACE, v, selector);
}
void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_DECOR, v, selector);
}
void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_ALIGN, v, selector);
}
void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_RADIUS, v, selector);
}
void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_CLIP_CORNER, v, selector);
}
void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, selector);
}
void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA_LAYERED, v, selector);
}
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_DSC, v, selector);
}
void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_OPA, v, selector);
}
void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM, v, selector);
}
void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_DURATION, v, selector);
}
void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSITION, v, selector);
}
void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BLEND_MODE, v, selector);
}
void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_LAYOUT, v, selector);
}
void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BASE_DIR, v, selector);
}
void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_BITMAP_MASK_SRC, v, selector);
}
void lv_obj_set_style_rotary_sensitivity(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ROTARY_SENSITIVITY, v, selector);
}
#if LV_USE_FLEX
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector);
}
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector);
}
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector);
}
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector);
}
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector);
}
#endif /*LV_USE_FLEX*/
#if LV_USE_GRID
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector);
}
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector);
}
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector);
}
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector);
}
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector);
}
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector);
}
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector);
}
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector);
}
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector);
}
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector);
}
#endif /*LV_USE_GRID*/

View File

@@ -1,875 +0,0 @@
/*
**********************************************************************
* DO NOT EDIT
* This file is automatically generated by "style_api_gen.py"
**********************************************************************
*/
#ifndef LV_OBJ_STYLE_GEN_H
#define LV_OBJ_STYLE_GEN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
#include "../core/lv_obj_style.h"
#include "../misc/lv_types.h"
static inline int32_t lv_obj_get_style_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_min_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_max_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_height(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_min_height(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_max_height(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_length(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LENGTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y);
return (int32_t)v.num;
}
static inline lv_align_t lv_obj_get_style_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ALIGN);
return (lv_align_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_height(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_translate_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_translate_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_scale_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SCALE_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_scale_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SCALE_Y);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_rotation(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ROTATION);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_pivot_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_pivot_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_Y);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_skew_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SKEW_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_transform_skew_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SKEW_Y);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_top(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_bottom(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_left(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_right(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_row(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_pad_column(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_margin_top(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_TOP);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_margin_bottom(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_BOTTOM);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_margin_left(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_LEFT);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_margin_right(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_RIGHT);
return (int32_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_bg_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_grad_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_GRAD_COLOR));
return v.color;
}
static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_DIR);
return (lv_grad_dir_t)v.num;
}
static inline int32_t lv_obj_get_style_bg_main_stop(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_bg_grad_stop(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP);
return (int32_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_bg_main_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_OPA);
return (lv_opa_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_bg_grad_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD);
return (const lv_grad_dsc_t *)v.ptr;
}
static inline const void * lv_obj_get_style_bg_image_src(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_SRC);
return (const void *)v.ptr;
}
static inline lv_opa_t lv_obj_get_style_bg_image_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_bg_image_recolor(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_bg_image_recolor_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_IMAGE_RECOLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_bg_image_recolor_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR_OPA);
return (lv_opa_t)v.num;
}
static inline bool lv_obj_get_style_bg_image_tiled(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_TILED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_border_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_border_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BORDER_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_border_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_OPA);
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_border_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH);
return (int32_t)v.num;
}
static inline lv_border_side_t lv_obj_get_style_border_side(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_SIDE);
return (lv_border_side_t)v.num;
}
static inline bool lv_obj_get_style_border_post(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST);
return (bool)v.num;
}
static inline int32_t lv_obj_get_style_outline_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH);
return (int32_t)v.num;
}
static inline lv_color_t lv_obj_get_style_outline_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_OUTLINE_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_outline_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_OPA);
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_outline_pad(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_shadow_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_shadow_offset_x(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFFSET_X);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_shadow_offset_y(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFFSET_Y);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_shadow_spread(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD);
return (int32_t)v.num;
}
static inline lv_color_t lv_obj_get_style_shadow_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_SHADOW_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_shadow_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OPA);
return (lv_opa_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_image_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_OPA);
return (lv_opa_t)v.num;
}
static inline lv_color_t lv_obj_get_style_image_recolor(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_image_recolor_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_IMAGE_RECOLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_image_recolor_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR_OPA);
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_line_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_line_dash_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_line_dash_gap(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP);
return (int32_t)v.num;
}
static inline bool lv_obj_get_style_line_rounded(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_line_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_line_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_line_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_OPA);
return (lv_opa_t)v.num;
}
static inline int32_t lv_obj_get_style_arc_width(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH);
return (int32_t)v.num;
}
static inline bool lv_obj_get_style_arc_rounded(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED);
return (bool)v.num;
}
static inline lv_color_t lv_obj_get_style_arc_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_arc_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_arc_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_OPA);
return (lv_opa_t)v.num;
}
static inline const void * lv_obj_get_style_arc_image_src(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMAGE_SRC);
return (const void *)v.ptr;
}
static inline lv_color_t lv_obj_get_style_text_color(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR);
return v.color;
}
static inline lv_color_t lv_obj_get_style_text_color_filtered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR));
return v.color;
}
static inline lv_opa_t lv_obj_get_style_text_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_font_t * lv_obj_get_style_text_font(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_FONT);
return (const lv_font_t *)v.ptr;
}
static inline int32_t lv_obj_get_style_text_letter_space(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_text_line_space(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE);
return (int32_t)v.num;
}
static inline lv_text_decor_t lv_obj_get_style_text_decor(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_DECOR);
return (lv_text_decor_t)v.num;
}
static inline lv_text_align_t lv_obj_get_style_text_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_ALIGN);
return (lv_text_align_t)v.num;
}
static inline int32_t lv_obj_get_style_radius(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS);
return (int32_t)v.num;
}
static inline bool lv_obj_get_style_clip_corner(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_CLIP_CORNER);
return (bool)v.num;
}
static inline lv_opa_t lv_obj_get_style_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA);
return (lv_opa_t)v.num;
}
static inline lv_opa_t lv_obj_get_style_opa_layered(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA_LAYERED);
return (lv_opa_t)v.num;
}
static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC);
return (const lv_color_filter_dsc_t *)v.ptr;
}
static inline lv_opa_t lv_obj_get_style_color_filter_opa(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA);
return (lv_opa_t)v.num;
}
static inline const lv_anim_t * lv_obj_get_style_anim(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM);
return (const lv_anim_t *)v.ptr;
}
static inline uint32_t lv_obj_get_style_anim_duration(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_DURATION);
return (uint32_t)v.num;
}
static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION);
return (const lv_style_transition_dsc_t *)v.ptr;
}
static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLEND_MODE);
return (lv_blend_mode_t)v.num;
}
static inline uint16_t lv_obj_get_style_layout(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LAYOUT);
return (uint16_t)v.num;
}
static inline lv_base_dir_t lv_obj_get_style_base_dir(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BASE_DIR);
return (lv_base_dir_t)v.num;
}
static inline const void * lv_obj_get_style_bitmap_mask_src(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BITMAP_MASK_SRC);
return (const void *)v.ptr;
}
static inline uint32_t lv_obj_get_style_rotary_sensitivity(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ROTARY_SENSITIVITY);
return (uint32_t)v.num;
}
#if LV_USE_FLEX
static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW);
return (lv_flex_flow_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE);
return (lv_flex_align_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE);
return (lv_flex_align_t)v.num;
}
static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE);
return (lv_flex_align_t)v.num;
}
static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW);
return (uint8_t)v.num;
}
#endif /*LV_USE_FLEX*/
#if LV_USE_GRID
static inline const int32_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY);
return (const int32_t *)v.ptr;
}
static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline const int32_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY);
return (const int32_t *)v.ptr;
}
static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline int32_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS);
return (int32_t)v.num;
}
static inline lv_grid_align_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline int32_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN);
return (int32_t)v.num;
}
static inline int32_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS);
return (int32_t)v.num;
}
static inline lv_grid_align_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN);
return (lv_grid_align_t)v.num;
}
static inline int32_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, lv_part_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN);
return (int32_t)v.num;
}
#endif /*LV_USE_GRID*/
void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_min_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_max_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_min_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_max_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_length(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_align(lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_translate_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_translate_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_scale_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_scale_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_rotation(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_pivot_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_pivot_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_skew_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transform_skew_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_row(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_pad_column(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_margin_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_margin_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_margin_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_margin_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_dir(lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_main_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_main_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_grad(lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_bg_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector);
void lv_obj_set_style_bg_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_bg_image_tiled(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_border_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_side(lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector);
void lv_obj_set_style_border_post(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_outline_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_outline_pad(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_offset_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_offset_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_spread(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_shadow_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_dash_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_dash_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_line_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_line_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_arc_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_arc_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector);
void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_font(lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector);
void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector);
void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector);
void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector);
void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector);
void lv_obj_set_style_rotary_sensitivity(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
#if LV_USE_FLEX
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector);
#endif /*LV_USE_FLEX*/
#if LV_USE_GRID
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector);
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector);
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
#endif /*LV_USE_GRID*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_OBJ_STYLE_GEN_H */

View File

@@ -1,95 +0,0 @@
/**
* @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;
};
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*/

View File

@@ -1,662 +0,0 @@
/**
* @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
/**********************
* 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);
/**********************
* 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;
}
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.last_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("parent:%p, obj:%p, id:%s;", (void *)(obj ? obj->parent : NULL), (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;
}

View File

@@ -1,237 +0,0 @@
/**
* @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_DELETED` 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_DELETED` 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);
/**
* 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*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +0,0 @@
/**
* @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);
/**********************
* STATIC FUNCTIONS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_REFR_H*/

View File

@@ -1,75 +0,0 @@
/**
* @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)
*/
void 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);
/**
* Called periodically to handle the refreshing
* @param timer pointer to the timer itself
*/
void lv_display_refr_timer(lv_timer_t * timer);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_REFR_PRIVATE_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,593 +0,0 @@
/**
* @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 "../draw/lv_draw.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 and address change is required.
*/
LV_DISPLAY_RENDER_MODE_FULL,
} lv_display_render_mode_t;
typedef enum {
LV_SCR_LOAD_ANIM_NONE,
LV_SCR_LOAD_ANIM_OVER_LEFT,
LV_SCR_LOAD_ANIM_OVER_RIGHT,
LV_SCR_LOAD_ANIM_OVER_TOP,
LV_SCR_LOAD_ANIM_OVER_BOTTOM,
LV_SCR_LOAD_ANIM_MOVE_LEFT,
LV_SCR_LOAD_ANIM_MOVE_RIGHT,
LV_SCR_LOAD_ANIM_MOVE_TOP,
LV_SCR_LOAD_ANIM_MOVE_BOTTOM,
LV_SCR_LOAD_ANIM_FADE_IN,
LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/
LV_SCR_LOAD_ANIM_FADE_OUT,
LV_SCR_LOAD_ANIM_OUT_LEFT,
LV_SCR_LOAD_ANIM_OUT_RIGHT,
LV_SCR_LOAD_ANIM_OUT_TOP,
LV_SCR_LOAD_ANIM_OUT_BOTTOM,
} lv_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);
/**
* 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 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 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 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 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);
/**
* 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);
//! @cond Doxygen_Suppress
/**
* 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);
//! @endcond
bool lv_display_is_double_buffered(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 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);
/**
* 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_SCR_LOAD_ANIM_MOVE_LEFT`
* @param time time of the animation
* @param delay delay before the transition
* @param auto_del true: automatically delete the old screen
*/
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);
/**
* 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);
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);
/**********************
* 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
/**
* Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP)
* 1 dip is 1 px on a 160 DPI screen
* 1 dip is 2 px on a 320 DPI screen
* 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)
/**
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
* considering the DPI of the default display.
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
* DPI of the display.
* @param n the number of pixels to scale
* @return `n x current_dpi/160`
*/
int32_t lv_dpx(int32_t n);
/**
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
* considering the DPI of the given display.
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
* DPI of the display.
* @param disp a display whose dpi should be considered
* @param n the number of pixels to scale
* @return `n x current_dpi/160`
*/
int32_t lv_display_dpx(const lv_display_t * disp, int32_t n);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DISPLAY_H*/

View File

@@ -1,181 +0,0 @@
/**
* @file lv_display_private.h
*
*/
#ifndef LV_DISPLAY_PRIVATE_H
#define LV_DISPLAY_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_types.h"
#include "../core/lv_obj.h"
#include "../draw/lv_draw.h"
#include "lv_display.h"
#if LV_USE_SYSMON
#include "../others/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 {
/*---------------------
* 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;
/** 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.*/
/** 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*/
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;
#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*/

View File

@@ -1,505 +0,0 @@
/**
* @file lv_draw.c
*
*/
/**
* Modified by NXP in 2024
*/
/*********************
* INCLUDES
*********************/
#include "../misc/lv_area_private.h"
#include "lv_draw_private.h"
#include "sw/lv_draw_sw.h"
#include "../display/lv_display_private.h"
#include "../core/lv_global.h"
#include "../core/lv_refr_private.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check);
static inline uint32_t get_layer_size_kb(uint32_t size_byte)
{
return size_byte < 1024 ? 1 : size_byte >> 10;
}
/**********************
* STATIC VARIABLES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_init(void)
{
#if LV_USE_OS
lv_thread_sync_init(&_draw_info.sync);
#endif
}
void lv_draw_deinit(void)
{
#if LV_USE_OS
lv_thread_sync_delete(&_draw_info.sync);
#endif
lv_draw_unit_t * u = _draw_info.unit_head;
while(u) {
lv_draw_unit_t * cur_unit = u;
u = u->next;
if(cur_unit->delete_cb) cur_unit->delete_cb(cur_unit);
lv_free(cur_unit);
}
_draw_info.unit_head = NULL;
}
void * lv_draw_create_unit(size_t size)
{
lv_draw_unit_t * new_unit = lv_malloc_zeroed(size);
new_unit->next = _draw_info.unit_head;
_draw_info.unit_head = new_unit;
_draw_info.unit_cnt++;
return new_unit;
}
lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords)
{
LV_PROFILER_BEGIN;
lv_draw_task_t * new_task = lv_malloc_zeroed(sizeof(lv_draw_task_t));
new_task->area = *coords;
new_task->_real_area = *coords;
new_task->clip_area = layer->_clip_area;
#if LV_DRAW_TRANSFORM_USE_MATRIX
new_task->matrix = layer->matrix;
#endif
new_task->state = LV_DRAW_TASK_STATE_QUEUED;
/*Find the tail*/
if(layer->draw_task_head == NULL) {
layer->draw_task_head = new_task;
}
else {
lv_draw_task_t * tail = layer->draw_task_head;
while(tail->next) tail = tail->next;
tail->next = new_task;
}
LV_PROFILER_END;
return new_task;
}
void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
{
LV_PROFILER_BEGIN;
lv_draw_dsc_base_t * base_dsc = t->draw_dsc;
base_dsc->layer = layer;
lv_draw_global_info_t * info = &_draw_info;
/*Send LV_EVENT_DRAW_TASK_ADDED and dispatch only on the "main" draw_task
*and not on the draw tasks added in the event.
*Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends and besides
*dispatching might remove the "main" draw task while it's still being used in the event*/
if(info->task_running == false) {
if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) {
info->task_running = true;
lv_obj_send_event(base_dsc->obj, LV_EVENT_DRAW_TASK_ADDED, t);
info->task_running = false;
}
/*Let the draw units set their preference score*/
t->preference_score = 100;
t->preferred_draw_unit_id = 0;
lv_draw_unit_t * u = info->unit_head;
while(u) {
if(u->evaluate_cb) u->evaluate_cb(u, t);
u = u->next;
}
lv_draw_dispatch();
}
else {
/*Let the draw units set their preference score*/
t->preference_score = 100;
t->preferred_draw_unit_id = 0;
lv_draw_unit_t * u = info->unit_head;
while(u) {
if(u->evaluate_cb) u->evaluate_cb(u, t);
u = u->next;
}
}
LV_PROFILER_END;
}
void lv_draw_wait_for_finish(void)
{
#if LV_USE_OS
lv_draw_unit_t * u = _draw_info.unit_head;
while(u) {
if(u->wait_for_finish_cb)
u->wait_for_finish_cb(u);
u = u->next;
}
#endif
}
void lv_draw_dispatch(void)
{
LV_PROFILER_BEGIN;
bool task_dispatched = false;
lv_display_t * disp = lv_display_get_next(NULL);
while(disp) {
lv_layer_t * layer = disp->layer_head;
while(layer) {
if(lv_draw_dispatch_layer(disp, layer))
task_dispatched = true;
layer = layer->next;
}
if(!task_dispatched) {
lv_draw_wait_for_finish();
lv_draw_dispatch_request();
}
disp = lv_display_get_next(disp);
}
LV_PROFILER_END;
}
bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer)
{
LV_PROFILER_BEGIN;
/*Remove the finished tasks first*/
lv_draw_task_t * t_prev = NULL;
lv_draw_task_t * t = layer->draw_task_head;
while(t) {
lv_draw_task_t * t_next = t->next;
if(t->state == LV_DRAW_TASK_STATE_READY) {
if(t_prev) t_prev->next = t->next; /*Remove it by assigning the next task to the previous*/
else layer->draw_task_head = t_next; /*If it was the head, set the next as head*/
/*If it was layer drawing free the layer too*/
if(t->type == LV_DRAW_TASK_TYPE_LAYER) {
lv_draw_image_dsc_t * draw_image_dsc = t->draw_dsc;
lv_layer_t * layer_drawn = (lv_layer_t *)draw_image_dsc->src;
if(layer_drawn->draw_buf) {
int32_t h = lv_area_get_height(&layer_drawn->buf_area);
uint32_t layer_size_byte = h * layer_drawn->draw_buf->header.stride;
_draw_info.used_memory_for_layers_kb -= get_layer_size_kb(layer_size_byte);
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb);
lv_draw_buf_destroy(layer_drawn->draw_buf);
layer_drawn->draw_buf = NULL;
}
/*Remove the layer from the display's*/
if(disp) {
lv_layer_t * l2 = disp->layer_head;
while(l2) {
if(l2->next == layer_drawn) {
l2->next = layer_drawn->next;
break;
}
l2 = l2->next;
}
if(disp->layer_deinit) disp->layer_deinit(disp, layer_drawn);
lv_free(layer_drawn);
}
}
lv_draw_label_dsc_t * draw_label_dsc = lv_draw_task_get_label_dsc(t);
if(draw_label_dsc && draw_label_dsc->text_local) {
lv_free((void *)draw_label_dsc->text);
draw_label_dsc->text = NULL;
}
lv_free(t->draw_dsc);
lv_free(t);
}
else {
t_prev = t;
}
t = t_next;
}
bool task_dispatched = false;
/*This layer is ready, enable blending its buffer*/
if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) {
/*Find a draw task with TYPE_LAYER in the layer where the src is this layer*/
lv_draw_task_t * t_src = layer->parent->draw_task_head;
while(t_src) {
if(t_src->type == LV_DRAW_TASK_TYPE_LAYER && t_src->state == LV_DRAW_TASK_STATE_WAITING) {
lv_draw_image_dsc_t * draw_dsc = t_src->draw_dsc;
if(draw_dsc->src == layer) {
t_src->state = LV_DRAW_TASK_STATE_QUEUED;
lv_draw_dispatch_request();
break;
}
}
t_src = t_src->next;
}
}
/*Assign draw tasks to the draw_units*/
else {
/*Find a draw unit which is not busy and can take at least one task*/
/*Let all draw units to pick draw tasks*/
lv_draw_unit_t * u = _draw_info.unit_head;
while(u) {
int32_t taken_cnt = u->dispatch_cb(u, layer);
if(taken_cnt != LV_DRAW_UNIT_IDLE) task_dispatched = true;
u = u->next;
}
}
LV_PROFILER_END;
return task_dispatched;
}
void lv_draw_dispatch_wait_for_request(void)
{
#if LV_USE_OS
lv_thread_sync_wait(&_draw_info.sync);
#else
while(!_draw_info.dispatch_req);
_draw_info.dispatch_req = 0;
#endif
}
void lv_draw_dispatch_request(void)
{
#if LV_USE_OS
lv_thread_sync_signal(&_draw_info.sync);
#else
_draw_info.dispatch_req = 1;
#endif
}
uint32_t lv_draw_get_unit_count(void)
{
return _draw_info.unit_cnt;
}
lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id)
{
LV_PROFILER_BEGIN;
/* If there is only 1 draw unit the task can be consumed linearly as
* they are added in the correct order. However, it can happen that
* there is a `LV_DRAW_TASK_TYPE_LAYER` which can be blended only when
* all its tasks are ready. As other areas might be on top of that
* layer-to-blend don't skip it. Instead stop there, so that the
* draw tasks of that layer can be consumed and can be finished.
* After that this layer-to-blenf will have `LV_DRAW_TASK_STATE_QUEUED`
* so it can be blended normally.*/
if(_draw_info.unit_cnt <= 1) {
lv_draw_task_t * t = layer->draw_task_head;
while(t) {
/*Mark unsupported draw tasks as ready as no one else will consume them*/
if(t->state == LV_DRAW_TASK_STATE_QUEUED &&
t->preferred_draw_unit_id != LV_DRAW_UNIT_NONE &&
t->preferred_draw_unit_id != draw_unit_id) {
t->state = LV_DRAW_TASK_STATE_READY;
}
/*Not queued yet, leave this layer while the first task will be queued*/
else if(t->state != LV_DRAW_TASK_STATE_QUEUED) {
t = NULL;
break;
}
/*It's a supported and queued task, process it*/
else {
break;
}
t = t->next;
}
LV_PROFILER_END;
return t;
}
/*Handle the case of multiply draw units*/
/*If the first task is screen sized, there cannot be independent areas*/
if(layer->draw_task_head) {
int32_t hor_res = lv_display_get_horizontal_resolution(lv_refr_get_disp_refreshing());
int32_t ver_res = lv_display_get_vertical_resolution(lv_refr_get_disp_refreshing());
lv_draw_task_t * t = layer->draw_task_head;
if(t->state != LV_DRAW_TASK_STATE_QUEUED &&
t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 &&
t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) {
LV_PROFILER_END;
return NULL;
}
}
lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head;
while(t) {
/*Find a queued and independent task*/
if(t->state == LV_DRAW_TASK_STATE_QUEUED &&
(t->preferred_draw_unit_id == LV_DRAW_UNIT_NONE || t->preferred_draw_unit_id == draw_unit_id) &&
is_independent(layer, t)) {
LV_PROFILER_END;
return t;
}
t = t->next;
}
LV_PROFILER_END;
return NULL;
}
uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check)
{
if(t_check == NULL) return 0;
if(t_check->next == NULL) return 0;
LV_PROFILER_BEGIN;
uint32_t cnt = 0;
lv_draw_task_t * t = t_check->next;
while(t) {
if((t->state == LV_DRAW_TASK_STATE_QUEUED || t->state == LV_DRAW_TASK_STATE_WAITING) &&
lv_area_is_on(&t_check->area, &t->area)) {
cnt++;
}
t = t->next;
}
LV_PROFILER_END;
return cnt;
}
lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area)
{
lv_display_t * disp = lv_refr_get_disp_refreshing();
lv_layer_t * new_layer = lv_malloc_zeroed(sizeof(lv_layer_t));
LV_ASSERT_MALLOC(new_layer);
if(new_layer == NULL) return NULL;
new_layer->parent = parent_layer;
new_layer->_clip_area = *area;
new_layer->buf_area = *area;
new_layer->phy_clip_area = *area;
new_layer->color_format = color_format;
#if LV_DRAW_TRANSFORM_USE_MATRIX
lv_matrix_identity(&new_layer->matrix);
#endif
if(disp->layer_head) {
lv_layer_t * tail = disp->layer_head;
while(tail->next) tail = tail->next;
tail->next = new_layer;
}
else {
disp->layer_head = new_layer;
}
return new_layer;
}
void * lv_draw_layer_alloc_buf(lv_layer_t * layer)
{
/*If the buffer of the layer is already allocated return it*/
if(layer->draw_buf != NULL) {
return layer->draw_buf->data;
}
/*If the buffer of the layer is not allocated yet, allocate it now*/
int32_t w = lv_area_get_width(&layer->buf_area);
int32_t h = lv_area_get_height(&layer->buf_area);
uint32_t layer_size_byte = h * lv_draw_buf_width_to_stride(w, layer->color_format);
layer->draw_buf = lv_draw_buf_create(w, h, layer->color_format, 0);
if(layer->draw_buf == NULL) {
LV_LOG_WARN("Allocating layer buffer failed. Try later");
return NULL;
}
_draw_info.used_memory_for_layers_kb += get_layer_size_kb(layer_size_byte);
LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb);
if(lv_color_format_has_alpha(layer->color_format)) {
lv_draw_buf_clear(layer->draw_buf, NULL);
}
return layer->draw_buf->data;
}
void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y)
{
return lv_draw_buf_goto_xy(layer->draw_buf, x, y);
}
lv_draw_task_type_t lv_draw_task_get_type(const lv_draw_task_t * t)
{
return t->type;
}
void * lv_draw_task_get_draw_dsc(const lv_draw_task_t * t)
{
return t->draw_dsc;
}
void lv_draw_task_get_area(const lv_draw_task_t * t, lv_area_t * area)
{
*area = t->area;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Check if there are older draw task overlapping the area of `t_check`
* @param layer the draw ctx to search in
* @param t_check check this task if it overlaps with the older ones
* @return true: `t_check` is not overlapping with older tasks so it's independent
*/
static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check)
{
LV_PROFILER_BEGIN;
lv_draw_task_t * t = layer->draw_task_head;
/*If t_check is outside of the older tasks then it's independent*/
while(t && t != t_check) {
if(t->state != LV_DRAW_TASK_STATE_READY) {
lv_area_t a;
if(lv_area_intersect(&a, &t->_real_area, &t_check->_real_area)) {
LV_PROFILER_END;
return false;
}
}
t = t->next;
}
LV_PROFILER_END;
return true;
}

View File

@@ -1,272 +0,0 @@
/**
* @file lv_draw.h
*
*/
/**
* Modified by NXP in 2024
*/
#ifndef LV_DRAW_H
#define LV_DRAW_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_text.h"
#include "../misc/lv_profiler.h"
#include "../misc/lv_matrix.h"
#include "lv_image_decoder.h"
#include "../osal/lv_os.h"
#include "lv_draw_buf.h"
/*********************
* DEFINES
*********************/
#define LV_DRAW_UNIT_NONE 0
#define LV_DRAW_UNIT_IDLE -1 /**< The draw unit is idle, new dispatching might be requested to try again */
#if LV_DRAW_TRANSFORM_USE_MATRIX
#if !LV_USE_MATRIX
#error "LV_DRAW_TRANSFORM_USE_MATRIX requires LV_USE_MATRIX = 1"
#endif
#endif
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_DRAW_TASK_TYPE_NONE = 0,
LV_DRAW_TASK_TYPE_FILL,
LV_DRAW_TASK_TYPE_BORDER,
LV_DRAW_TASK_TYPE_BOX_SHADOW,
LV_DRAW_TASK_TYPE_LABEL,
LV_DRAW_TASK_TYPE_IMAGE,
LV_DRAW_TASK_TYPE_LAYER,
LV_DRAW_TASK_TYPE_LINE,
LV_DRAW_TASK_TYPE_ARC,
LV_DRAW_TASK_TYPE_TRIANGLE,
LV_DRAW_TASK_TYPE_MASK_RECTANGLE,
LV_DRAW_TASK_TYPE_MASK_BITMAP,
LV_DRAW_TASK_TYPE_VECTOR,
} lv_draw_task_type_t;
typedef enum {
LV_DRAW_TASK_STATE_WAITING, /*Waiting for something to be finished. E.g. rendering a layer*/
LV_DRAW_TASK_STATE_QUEUED,
LV_DRAW_TASK_STATE_IN_PROGRESS,
LV_DRAW_TASK_STATE_READY,
} lv_draw_task_state_t;
struct lv_layer_t {
/** Target draw buffer of the layer*/
lv_draw_buf_t * draw_buf;
/** The absolute coordinates of the buffer */
lv_area_t buf_area;
/** The color format of the layer. LV_COLOR_FORMAT_... */
lv_color_format_t color_format;
/**
* NEVER USE IT DRAW UNITS. USED INTERNALLY DURING DRAW TASK CREATION.
* The current clip area with absolute coordinates, always the same or smaller than `buf_area`
* Can be set before new draw tasks are added to indicate the clip area of the draw tasks.
* Therefore `lv_draw_add_task()` always saves it in the new draw task to know the clip area when the draw task was added.
* During drawing the draw units also sees the saved clip_area and should use it during drawing.
* During drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks.
*/
lv_area_t _clip_area;
/**
* The physical clipping area relative to the display.
*/
lv_area_t phy_clip_area;
#if LV_DRAW_TRANSFORM_USE_MATRIX
/** Transform matrix to be applied when rendering the layer */
lv_matrix_t matrix;
#endif
/** Linked list of draw tasks */
lv_draw_task_t * draw_task_head;
lv_layer_t * parent;
lv_layer_t * next;
bool all_tasks_added;
void * user_data;
};
typedef struct {
lv_obj_t * obj;
lv_part_t part;
uint32_t id1;
uint32_t id2;
lv_layer_t * layer;
size_t dsc_size;
void * user_data;
} lv_draw_dsc_base_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Used internally to initialize the drawing module
*/
void lv_draw_init(void);
/**
* Deinitialize the drawing module
*/
void lv_draw_deinit(void);
/**
* Allocate a new draw unit with the given size and appends it to the list of draw units
* @param size the size to allocate. E.g. `sizeof(my_draw_unit_t)`,
* where the first element of `my_draw_unit_t` is `lv_draw_unit_t`.
*/
void * lv_draw_create_unit(size_t size);
/**
* Add an empty draw task to the draw task list of a layer.
* @param layer pointer to a layer
* @param coords the coordinates of the draw task
* @return the created draw task which needs to be
* further configured e.g. by added a draw descriptor
*/
lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords);
/**
* Needs to be called when a draw task is created and configured.
* It will send an event about the new draw task to the widget
* and assign it to a draw unit.
* @param layer pointer to a layer
* @param t pointer to a draw task
*/
void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t);
/**
* Try dispatching draw tasks to draw units
*/
void lv_draw_dispatch(void);
/**
* Used internally to try dispatching draw tasks of a specific layer
* @param disp pointer to a display on which the dispatching was requested
* @param layer pointer to a layer
* @return at least one draw task is being rendered (maybe it was taken earlier)
*/
bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer);
/**
* Wait for a new dispatch request.
* It's blocking if `LV_USE_OS == 0` else it yields
*/
void lv_draw_dispatch_wait_for_request(void);
/**
* Wait for draw finish in case of asynchronous task execution.
* If `LV_USE_OS == 0` it just return.
*/
void lv_draw_wait_for_finish(void);
/**
* When a draw unit finished a draw task it needs to request dispatching
* to let LVGL assign a new draw task to it
*/
void lv_draw_dispatch_request(void);
/**
* Get the total number of draw units.
*/
uint32_t lv_draw_get_unit_count(void);
/**
* Find and available draw task
* @param layer the draw ctx to search in
* @param t_prev continue searching from this task
* @param draw_unit_id check the task where `preferred_draw_unit_id` equals this value or `LV_DRAW_UNIT_NONE`
* @return tan available draw task or NULL if there is no any
*/
lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id);
/**
* Tell how many draw task are waiting to be drawn on the area of `t_check`.
* It can be used to determine if a GPU shall combine many draw tasks into one or not.
* If a lot of tasks are waiting for the current ones it makes sense to draw them one-by-one
* to not block the dependent tasks' rendering
* @param t_check the task whose dependent tasks shall be counted
* @return number of tasks depending on `t_check`
*/
uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check);
/**
* Create a new layer on a parent layer
* @param parent_layer the parent layer to which the layer will be merged when it's rendered
* @param color_format the color format of the layer
* @param area the areas of the layer (absolute coordinates)
* @return the new target_layer or NULL on error
*/
lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area);
/**
* Try to allocate a buffer for the layer.
* @param layer pointer to a layer
* @return pointer to the allocated aligned buffer or NULL on failure
*/
void * lv_draw_layer_alloc_buf(lv_layer_t * layer);
/**
* Got to a pixel at X and Y coordinate on a layer
* @param layer pointer to a layer
* @param x the target X coordinate
* @param y the target X coordinate
* @return `buf` offset to point to the given X and Y coordinate
*/
void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y);
/**
* Get the type of a draw task
* @param t the draw task to get the type of
* @return the draw task type
*/
lv_draw_task_type_t lv_draw_task_get_type(const lv_draw_task_t * t);
/**
* Get the draw descriptor of a draw task
* @param t the draw task to get the draw descriptor of
* @return a void pointer to the draw descriptor
*/
void * lv_draw_task_get_draw_dsc(const lv_draw_task_t * t);
/**
* Get the draw area of a draw task
* @param t the draw task to get the draw area of
* @param area the destination where the draw area will be stored
*/
void lv_draw_task_get_area(const lv_draw_task_t * t, lv_area_t * area);
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_H*/

View File

@@ -1,174 +0,0 @@
/**
* @file lv_draw_arc.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_private.h"
#include "../core/lv_obj.h"
#include "lv_draw_arc.h"
#include "../core/lv_obj_event.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_arc_dsc_t));
dsc->width = 1;
dsc->opa = LV_OPA_COVER;
dsc->color = lv_color_black();
dsc->base.dsc_size = sizeof(lv_draw_arc_dsc_t);
}
lv_draw_arc_dsc_t * lv_draw_task_get_arc_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_ARC ? (lv_draw_arc_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_arc(lv_layer_t * layer, const lv_draw_arc_dsc_t * dsc)
{
if(dsc->opa <= LV_OPA_MIN) return;
if(dsc->width == 0) return;
if(dsc->start_angle == dsc->end_angle) return;
LV_PROFILER_BEGIN;
lv_area_t a;
a.x1 = dsc->center.x - dsc->radius;
a.y1 = dsc->center.y - dsc->radius;
a.x2 = dsc->center.x + dsc->radius - 1;
a.y2 = dsc->center.y + dsc->radius - 1;
lv_draw_task_t * t = lv_draw_add_task(layer, &a);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_ARC;
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
void lv_draw_arc_get_area(int32_t x, int32_t y, uint16_t radius, lv_value_precise_t start_angle,
lv_value_precise_t end_angle,
int32_t w, bool rounded, lv_area_t * area)
{
int32_t rout = radius;
int32_t start_angle_int = (int32_t) start_angle;
int32_t end_angle_int = (int32_t) end_angle;
/*Special case: full arc invalidation */
if(end_angle_int == start_angle_int + 360) {
area->x1 = x - rout;
area->y1 = y - rout;
area->x2 = x + rout;
area->y2 = y + rout;
return;
}
if(start_angle_int > 360) start_angle_int -= 360;
if(end_angle_int > 360) end_angle_int -= 360;
int32_t rin = radius - w;
int32_t extra_area = rounded ? w / 2 + 1 : 0;
uint8_t start_quarter = start_angle_int / 90;
uint8_t end_quarter = end_angle_int / 90;
/*360 deg still counts as quarter 3 (360 / 90 would be 4)*/
if(start_quarter == 4) start_quarter = 3;
if(end_quarter == 4) end_quarter = 3;
if(start_quarter == end_quarter && start_angle_int <= end_angle_int) {
if(start_quarter == 0) {
area->y1 = y + ((lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->y2 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
}
else if(start_quarter == 1) {
area->y2 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
area->y1 = y + ((lv_trigo_sin(end_angle_int) * rin) >> LV_TRIGO_SHIFT) - extra_area;
area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
}
else if(start_quarter == 2) {
area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->y2 = y + ((lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area;
area->y1 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
}
else if(start_quarter == 3) {
area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
area->y1 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->y2 = y + ((lv_trigo_sin(end_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area;
}
}
else if(start_quarter == 0 && end_quarter == 1) {
area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle_int),
lv_trigo_sin(start_angle_int)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->y2 = y + rout + extra_area;
}
else if(start_quarter == 1 && end_quarter == 2) {
area->x1 = x - rout - extra_area;
area->y1 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle_int + 90),
lv_trigo_sin(end_angle_int + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area;
area->y2 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area;
}
else if(start_quarter == 2 && end_quarter == 3) {
area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->y1 = y - rout - extra_area;
area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle_int) * rin,
lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area;
}
else if(start_quarter == 3 && end_quarter == 0) {
area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle_int + 90),
lv_trigo_sin(start_angle_int + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
area->y1 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area;
area->x2 = x + rout + extra_area;
area->y2 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area;
}
else {
area->x1 = x - rout;
area->y1 = y - rout;
area->x2 = x + rout;
area->y2 = y + rout;
}
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,90 +0,0 @@
/**
* @file lv_draw_arc.h
*
*/
#ifndef LV_DRAW_ARC_H
#define LV_DRAW_ARC_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
lv_color_t color;
int32_t width;
lv_value_precise_t start_angle;
lv_value_precise_t end_angle;
lv_point_t center;
uint16_t radius;
const void * img_src;
lv_opa_t opa;
uint8_t rounded : 1;
} lv_draw_arc_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize an arc draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc);
/**
* Try to get an arc draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_ARC
*/
lv_draw_arc_dsc_t * lv_draw_task_get_arc_dsc(lv_draw_task_t * task);
/**
* Create an arc draw task.
* @param layer pointer to a layer
* @param dsc pointer to an initialized draw descriptor variable
*/
void lv_draw_arc(lv_layer_t * layer, const lv_draw_arc_dsc_t * dsc);
/**
* Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange
* @param x the x coordinate of the center of the arc
* @param y the y coordinate of the center of the arc
* @param radius the radius of the arc
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
* @param end_angle the end angle of the arc
* @param w width of the arc
* @param rounded true: the arc is rounded
* @param area store the area to invalidate here
*/
void lv_draw_arc_get_area(int32_t x, int32_t y, uint16_t radius, lv_value_precise_t start_angle,
lv_value_precise_t end_angle,
int32_t w, bool rounded, lv_area_t * area);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_ARC_H*/

View File

@@ -1,669 +0,0 @@
/**
* @file lv_draw_buf.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_buf_private.h"
#include "../misc/lv_types.h"
#include "../stdlib/lv_string.h"
#include "../core/lv_global.h"
#include "../misc/lv_math.h"
#include "../misc/lv_area_private.h"
/*********************
* DEFINES
*********************/
#define default_handlers LV_GLOBAL_DEFAULT()->draw_buf_handlers
#define font_draw_buf_handlers LV_GLOBAL_DEFAULT()->font_draw_buf_handlers
#define image_cache_draw_buf_handlers LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void * buf_malloc(size_t size, lv_color_format_t color_format);
static void buf_free(void * buf);
static void * buf_align(void * buf, lv_color_format_t color_format);
static void * draw_buf_malloc(const lv_draw_buf_handlers_t * handler, size_t size_bytes,
lv_color_format_t color_format);
static void draw_buf_free(const lv_draw_buf_handlers_t * handler, void * buf);
static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format);
static uint32_t _calculate_draw_buf_size(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride);
static void draw_buf_get_full_area(const lv_draw_buf_t * draw_buf, lv_area_t * full_area);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_buf_init_handlers(void)
{
lv_draw_buf_init_with_default_handlers(&default_handlers);
lv_draw_buf_init_with_default_handlers(&font_draw_buf_handlers);
lv_draw_buf_init_with_default_handlers(&image_cache_draw_buf_handlers);
}
void lv_draw_buf_init_with_default_handlers(lv_draw_buf_handlers_t * handlers)
{
lv_draw_buf_handlers_init(handlers, buf_malloc, buf_free, buf_align, NULL, NULL, width_to_stride);
}
void lv_draw_buf_handlers_init(lv_draw_buf_handlers_t * handlers,
lv_draw_buf_malloc_cb buf_malloc_cb,
lv_draw_buf_free_cb buf_free_cb,
lv_draw_buf_align_cb align_pointer_cb,
lv_draw_buf_cache_operation_cb invalidate_cache_cb,
lv_draw_buf_cache_operation_cb flush_cache_cb,
lv_draw_buf_width_to_stride_cb width_to_stride_cb)
{
lv_memzero(handlers, sizeof(lv_draw_buf_handlers_t));
handlers->buf_malloc_cb = buf_malloc_cb;
handlers->buf_free_cb = buf_free_cb;
handlers->align_pointer_cb = align_pointer_cb;
handlers->invalidate_cache_cb = invalidate_cache_cb;
handlers->flush_cache_cb = flush_cache_cb;
handlers->width_to_stride_cb = width_to_stride_cb;
}
lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void)
{
return &default_handlers;
}
lv_draw_buf_handlers_t * lv_draw_buf_get_font_handlers(void)
{
return &font_draw_buf_handlers;
}
lv_draw_buf_handlers_t * lv_draw_buf_get_image_handlers(void)
{
return &image_cache_draw_buf_handlers;
}
uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format)
{
return lv_draw_buf_width_to_stride_ex(&default_handlers, w, color_format);
}
uint32_t lv_draw_buf_width_to_stride_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w,
lv_color_format_t color_format)
{
if(handlers->width_to_stride_cb) return handlers->width_to_stride_cb(w, color_format);
else return 0;
}
void * lv_draw_buf_align(void * data, lv_color_format_t color_format)
{
return lv_draw_buf_align_ex(&default_handlers, data, color_format);
}
void * lv_draw_buf_align_ex(const lv_draw_buf_handlers_t * handlers, void * data, lv_color_format_t color_format)
{
if(handlers->align_pointer_cb) return handlers->align_pointer_cb(data, color_format);
else return NULL;
}
void lv_draw_buf_invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
LV_ASSERT_NULL(draw_buf);
LV_ASSERT_NULL(draw_buf->handlers);
const lv_draw_buf_handlers_t * handlers = draw_buf->handlers;
if(!handlers->invalidate_cache_cb) {
return;
}
lv_area_t full;
if(area == NULL) {
draw_buf_get_full_area(draw_buf, &full);
area = &full;
}
handlers->invalidate_cache_cb(draw_buf, area);
}
void lv_draw_buf_flush_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
LV_ASSERT_NULL(draw_buf);
LV_ASSERT_NULL(draw_buf->handlers);
const lv_draw_buf_handlers_t * handlers = draw_buf->handlers;
if(!handlers->flush_cache_cb) {
return;
}
lv_area_t full;
if(area == NULL) {
draw_buf_get_full_area(draw_buf, &full);
area = &full;
}
handlers->flush_cache_cb(draw_buf, area);
}
void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a)
{
LV_ASSERT_NULL(draw_buf);
const lv_image_header_t * header = &draw_buf->header;
uint32_t stride = header->stride;
if(a == NULL) {
uint8_t * buf = lv_draw_buf_goto_xy(draw_buf, 0, 0);
lv_memzero(buf, header->h * stride);
return;
}
lv_area_t a_draw_buf;
a_draw_buf.x1 = 0;
a_draw_buf.y1 = 0;
a_draw_buf.x2 = draw_buf->header.w - 1;
a_draw_buf.y2 = draw_buf->header.h - 1;
lv_area_t a_clipped;
if(!lv_area_intersect(&a_clipped, a, &a_draw_buf)) return;
if(lv_area_get_width(&a_clipped) <= 0) return;
if(lv_area_get_height(&a_clipped) <= 0) return;
uint8_t * buf = lv_draw_buf_goto_xy(draw_buf, a_clipped.x1, a_clipped.y1);
uint8_t bpp = lv_color_format_get_bpp(header->cf);
uint32_t line_length = (lv_area_get_width(&a_clipped) * bpp + 7) >> 3;
int32_t y;
for(y = a_clipped.y1; y <= a_clipped.y2; y++) {
lv_memzero(buf, line_length);
buf += stride;
}
}
void lv_draw_buf_copy(lv_draw_buf_t * dest, const lv_area_t * dest_area,
const lv_draw_buf_t * src, const lv_area_t * src_area)
{
uint8_t * dest_bufc;
uint8_t * src_bufc;
int32_t line_width;
/*Source and dest color format must be same. Color conversion is not supported yet.*/
LV_ASSERT_FORMAT_MSG(dest->header.cf == src->header.cf, "Color format mismatch: %d != %d",
dest->header.cf, src->header.cf);
if(dest_area == NULL) line_width = dest->header.w;
else line_width = lv_area_get_width(dest_area);
/* For indexed image, copy the palette if we are copying full image area*/
if(dest_area == NULL || src_area == NULL) {
if(LV_COLOR_FORMAT_IS_INDEXED(dest->header.cf)) {
lv_memcpy(dest->data, src->data, LV_COLOR_INDEXED_PALETTE_SIZE(dest->header.cf) * sizeof(lv_color32_t));
}
}
/*Check source and dest area have same width*/
if((src_area == NULL && line_width != src->header.w) || \
(src_area != NULL && line_width != lv_area_get_width(src_area))) {
LV_ASSERT_MSG(0, "Source and destination areas have different width");
return;
}
if(src_area) src_bufc = lv_draw_buf_goto_xy(src, src_area->x1, src_area->y1);
else src_bufc = lv_draw_buf_goto_xy(src, 0, 0);
if(dest_area) dest_bufc = lv_draw_buf_goto_xy(dest, dest_area->x1, dest_area->y1);
else dest_bufc = lv_draw_buf_goto_xy(dest, 0, 0);
int32_t start_y, end_y;
if(dest_area) {
start_y = dest_area->y1;
end_y = dest_area->y2;
}
else {
start_y = 0;
end_y = dest->header.h - 1;
}
uint32_t dest_stride = dest->header.stride;
uint32_t src_stride = src->header.stride;
uint32_t line_bytes = (line_width * lv_color_format_get_bpp(dest->header.cf) + 7) >> 3;
for(; start_y <= end_y; start_y++) {
lv_memcpy(dest_bufc, src_bufc, line_bytes);
dest_bufc += dest_stride;
src_bufc += src_stride;
}
}
lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride,
void * data, uint32_t data_size)
{
LV_ASSERT_NULL(draw_buf);
if(draw_buf == NULL) return LV_RESULT_INVALID;
lv_memzero(draw_buf, sizeof(lv_draw_buf_t));
if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf);
if(stride * h > data_size) {
LV_LOG_WARN("Data size too small, required: %" LV_PRId32 ", provided: %" LV_PRId32, stride * h,
data_size);
return LV_RESULT_INVALID;
}
lv_image_header_t * header = &draw_buf->header;
header->w = w;
header->h = h;
header->cf = cf;
header->stride = stride;
header->flags = 0;
header->magic = LV_IMAGE_HEADER_MAGIC;
draw_buf->data = data;
draw_buf->unaligned_data = data;
draw_buf->handlers = &default_handlers;
draw_buf->data_size = data_size;
if(lv_draw_buf_align(data, cf) != draw_buf->unaligned_data) {
LV_LOG_WARN("Data is not aligned, ignored");
}
return LV_RESULT_OK;
}
lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride)
{
return lv_draw_buf_create_ex(&default_handlers, w, h, cf, stride);
}
lv_draw_buf_t * lv_draw_buf_create_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w, uint32_t h,
lv_color_format_t cf, uint32_t stride)
{
lv_draw_buf_t * draw_buf = lv_malloc_zeroed(sizeof(lv_draw_buf_t));
LV_ASSERT_MALLOC(draw_buf);
if(draw_buf == NULL) return NULL;
if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf);
uint32_t size = _calculate_draw_buf_size(w, h, cf, stride);
void * buf = draw_buf_malloc(handlers, size, cf);
/*Do not assert here as LVGL or the app might just want to try creating a draw_buf*/
if(buf == NULL) {
LV_LOG_WARN("No memory: %"LV_PRIu32"x%"LV_PRIu32", cf: %d, stride: %"LV_PRIu32", %"LV_PRIu32"Byte, ",
w, h, cf, stride, size);
lv_free(draw_buf);
return NULL;
}
draw_buf->header.w = w;
draw_buf->header.h = h;
draw_buf->header.cf = cf;
draw_buf->header.flags = LV_IMAGE_FLAGS_MODIFIABLE | LV_IMAGE_FLAGS_ALLOCATED;
draw_buf->header.stride = stride;
draw_buf->header.magic = LV_IMAGE_HEADER_MAGIC;
draw_buf->data = lv_draw_buf_align(buf, cf);
draw_buf->unaligned_data = buf;
draw_buf->data_size = size;
draw_buf->handlers = handlers;
return draw_buf;
}
lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf)
{
return lv_draw_buf_dup_ex(&default_handlers, draw_buf);
}
lv_draw_buf_t * lv_draw_buf_dup_ex(const lv_draw_buf_handlers_t * handlers, const lv_draw_buf_t * draw_buf)
{
const lv_image_header_t * header = &draw_buf->header;
lv_draw_buf_t * new_buf = lv_draw_buf_create_ex(handlers, header->w, header->h, header->cf, header->stride);
if(new_buf == NULL) return NULL;
new_buf->header.flags = draw_buf->header.flags;
new_buf->header.flags |= LV_IMAGE_FLAGS_MODIFIABLE | LV_IMAGE_FLAGS_ALLOCATED;
/*Choose the smaller size to copy*/
uint32_t size = LV_MIN(draw_buf->data_size, new_buf->data_size);
/*Copy image data*/
lv_memcpy(new_buf->data, draw_buf->data, size);
return new_buf;
}
lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t cf, uint32_t w, uint32_t h,
uint32_t stride)
{
if(draw_buf == NULL) return NULL;
/*If color format is unknown, keep using the original color format.*/
if(cf == LV_COLOR_FORMAT_UNKNOWN) cf = draw_buf->header.cf;
if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf);
uint32_t size = _calculate_draw_buf_size(w, h, cf, stride);
if(size > draw_buf->data_size) {
LV_LOG_TRACE("Draw buf too small for new shape");
return NULL;
}
draw_buf->header.cf = cf;
draw_buf->header.w = w;
draw_buf->header.h = h;
draw_buf->header.stride = stride;
return draw_buf;
}
void lv_draw_buf_destroy(lv_draw_buf_t * draw_buf)
{
LV_ASSERT_NULL(draw_buf);
if(draw_buf == NULL) return;
if(draw_buf->header.flags & LV_IMAGE_FLAGS_ALLOCATED) {
LV_ASSERT_NULL(draw_buf->handlers);
const lv_draw_buf_handlers_t * handlers = draw_buf->handlers;
draw_buf_free(handlers, draw_buf->unaligned_data);
lv_free(draw_buf);
}
else {
LV_LOG_ERROR("draw buffer is not allocated, ignored");
}
}
void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y)
{
LV_ASSERT_NULL(buf);
if(buf == NULL) return NULL;
uint8_t * data = buf->data;
/*Skip palette*/
data += LV_COLOR_INDEXED_PALETTE_SIZE(buf->header.cf) * sizeof(lv_color32_t);
data += buf->header.stride * y;
if(x == 0) return data;
return data + x * lv_color_format_get_bpp(buf->header.cf) / 8;
}
lv_result_t lv_draw_buf_adjust_stride(lv_draw_buf_t * src, uint32_t stride)
{
LV_ASSERT_NULL(src);
LV_ASSERT_NULL(src->data);
if(src == NULL) return LV_RESULT_INVALID;
if(src->data == NULL) return LV_RESULT_INVALID;
const lv_image_header_t * header = &src->header;
uint32_t w = header->w;
uint32_t h = header->h;
if(!lv_draw_buf_has_flag(src, LV_IMAGE_FLAGS_MODIFIABLE)) {
return LV_RESULT_INVALID;
}
/*Use global stride*/
if(stride == 0) stride = lv_draw_buf_width_to_stride(w, header->cf);
/*Check if stride already match*/
if(header->stride == stride) return LV_RESULT_OK;
/*Calculate the minimal stride allowed from bpp*/
uint32_t bpp = lv_color_format_get_bpp(header->cf);
uint32_t min_stride = (w * bpp + 7) >> 3;
if(stride < min_stride) {
LV_LOG_WARN("New stride is too small. min: %" LV_PRId32, min_stride);
return LV_RESULT_INVALID;
}
/*Check if buffer has enough space. */
uint32_t new_size = _calculate_draw_buf_size(w, h, header->cf, stride);
if(new_size > src->data_size) {
return LV_RESULT_INVALID;
}
uint32_t offset = LV_COLOR_INDEXED_PALETTE_SIZE(header->cf) * 4;
if(stride > header->stride) {
/*Copy from the last line to the first*/
uint8_t * src_data = src->data + offset + header->stride * (h - 1);
uint8_t * dst_data = src->data + offset + stride * (h - 1);
for(uint32_t y = 0; y < h; y++) {
lv_memmove(dst_data, src_data, min_stride);
src_data -= header->stride;
dst_data -= stride;
}
}
else {
/*Copy from the first line to the last*/
uint8_t * src_data = src->data + offset;
uint8_t * dst_data = src->data + offset;
for(uint32_t y = 0; y < h; y++) {
lv_memmove(dst_data, src_data, min_stride);
src_data += header->stride;
dst_data += stride;
}
}
src->header.stride = stride;
return LV_RESULT_OK;
}
lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf)
{
LV_ASSERT_NULL(draw_buf);
if(draw_buf == NULL) return LV_RESULT_INVALID;
if(draw_buf->header.flags & LV_IMAGE_FLAGS_PREMULTIPLIED) return LV_RESULT_INVALID;
if((draw_buf->header.flags & LV_IMAGE_FLAGS_MODIFIABLE) == 0) {
LV_LOG_WARN("draw buf is not modifiable: 0x%04x", draw_buf->header.flags);
return LV_RESULT_INVALID;
}
/*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)) {
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) {
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) {
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) {
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 if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
/*Pass*/
}
else {
LV_LOG_WARN("draw buf has no alpha, cf: %d", cf);
}
draw_buf->header.flags |= LV_IMAGE_FLAGS_PREMULTIPLIED;
return LV_RESULT_OK;
}
void lv_draw_buf_set_palette(lv_draw_buf_t * draw_buf, uint8_t index, lv_color32_t color)
{
LV_ASSERT_NULL(draw_buf);
if(draw_buf == NULL) return;
if(!LV_COLOR_FORMAT_IS_INDEXED(draw_buf->header.cf)) {
LV_LOG_WARN("Not indexed color format");
return;
}
lv_color32_t * palette = (lv_color32_t *)draw_buf->data;
palette[index] = color;
}
bool lv_draw_buf_has_flag(const lv_draw_buf_t * draw_buf, lv_image_flags_t flag)
{
return draw_buf->header.flags & flag;
}
void lv_draw_buf_set_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag)
{
draw_buf->header.flags |= flag;
}
void lv_draw_buf_clear_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag)
{
draw_buf->header.flags &= ~flag;
}
void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img)
{
lv_draw_buf_init(buf, img->header.w, img->header.h, img->header.cf, img->header.stride,
(void *)img->data, img->data_size);
buf->header.flags = img->header.flags;
}
void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img)
{
lv_memcpy((void *)img, buf, sizeof(lv_image_dsc_t));
}
void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c)
{
LV_LOG_WARN("Deprecated API, use lv_draw_buf_set_palette instead.");
lv_draw_buf_set_palette((lv_draw_buf_t *)dsc, id, c);
}
void lv_image_buf_free(lv_image_dsc_t * dsc)
{
LV_LOG_WARN("Deprecated API, use lv_draw_buf_destroy instead.");
if(dsc != NULL) {
if(dsc->data != NULL)
lv_free((void *)dsc->data);
lv_free((void *)dsc);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
static void * buf_malloc(size_t size_bytes, lv_color_format_t color_format)
{
LV_UNUSED(color_format);
/*Allocate larger memory to be sure it can be aligned as needed*/
size_bytes += LV_DRAW_BUF_ALIGN - 1;
return lv_malloc(size_bytes);
}
static void buf_free(void * buf)
{
lv_free(buf);
}
static void * buf_align(void * buf, lv_color_format_t color_format)
{
LV_UNUSED(color_format);
uint8_t * buf_u8 = buf;
if(buf_u8) {
buf_u8 = (uint8_t *)LV_ROUND_UP((lv_uintptr_t)buf_u8, LV_DRAW_BUF_ALIGN);
}
return buf_u8;
}
static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format)
{
uint32_t width_byte;
width_byte = w * lv_color_format_get_bpp(color_format);
width_byte = (width_byte + 7) >> 3; /*Round up*/
return LV_ROUND_UP(width_byte, LV_DRAW_BUF_STRIDE_ALIGN);
}
static void * draw_buf_malloc(const lv_draw_buf_handlers_t * handlers, size_t size_bytes,
lv_color_format_t color_format)
{
if(handlers->buf_malloc_cb) return handlers->buf_malloc_cb(size_bytes, color_format);
else return NULL;
}
static void draw_buf_free(const lv_draw_buf_handlers_t * handlers, void * buf)
{
if(handlers->buf_free_cb)
handlers->buf_free_cb(buf);
}
/**
* For given width, height, color format, and stride, calculate the size needed for a new draw buffer.
*/
static uint32_t _calculate_draw_buf_size(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride)
{
uint32_t size;
if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf);
size = stride * h;
if(cf == LV_COLOR_FORMAT_RGB565A8) {
size += (stride / 2) * h; /*A8 mask*/
}
else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
/*@todo we have to include palette right before image data*/
size += LV_COLOR_INDEXED_PALETTE_SIZE(cf) * 4;
}
return size;
}
static void draw_buf_get_full_area(const lv_draw_buf_t * draw_buf, lv_area_t * full_area)
{
const lv_image_header_t * header = &draw_buf->header;
lv_area_set(full_area, 0, 0, header->w - 1, header->h - 1);
}

View File

@@ -1,356 +0,0 @@
/**
* @file lv_draw_buf.h
*
*/
#ifndef LV_DRAW_BUF_H
#define LV_DRAW_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_types.h"
#include "../misc/lv_area.h"
#include "../misc/lv_color.h"
#include "../stdlib/lv_string.h"
#include "lv_image_dsc.h"
/*********************
* DEFINES
*********************/
/** Use this value to let LVGL calculate stride automatically */
#define LV_STRIDE_AUTO 0
LV_EXPORT_CONST_INT(LV_STRIDE_AUTO);
/**
* Stride alignment for draw buffers.
* It may vary between different color formats and hardware.
* Refine it to suit your needs.
*/
#define LV_DRAW_BUF_STRIDE(w, cf) \
LV_ROUND_UP(((w) * LV_COLOR_FORMAT_GET_BPP(cf) + 7) / 8, LV_DRAW_BUF_STRIDE_ALIGN)
/** Allocate a slightly larger buffer, so we can adjust the start address to meet alignment */
#define LV_DRAW_BUF_SIZE(w, h, cf) \
(LV_DRAW_BUF_STRIDE(w, cf) * (h) + LV_DRAW_BUF_ALIGN + \
LV_COLOR_INDEXED_PALETTE_SIZE(cf) * sizeof(lv_color32_t))
/**
* Define a static draw buffer with the given width, height, and color format.
* Stride alignment is set to LV_DRAW_BUF_STRIDE_ALIGN.
*
* For platform that needs special buffer alignment, call LV_DRAW_BUF_INIT_STATIC.
*/
#define LV_DRAW_BUF_DEFINE_STATIC(name, _w, _h, _cf) \
static uint8_t buf_##name[LV_DRAW_BUF_SIZE(_w, _h, _cf)]; \
static lv_draw_buf_t name = { \
.header = { \
.magic = LV_IMAGE_HEADER_MAGIC, \
.cf = (_cf), \
.flags = LV_IMAGE_FLAGS_MODIFIABLE, \
.w = (_w), \
.h = (_h), \
.stride = LV_DRAW_BUF_STRIDE(_w, _cf), \
.reserved_2 = 0, \
}, \
.data_size = sizeof(buf_##name), \
.data = buf_##name, \
.unaligned_data = buf_##name, \
}
#define LV_DRAW_BUF_INIT_STATIC(name) \
do { \
lv_image_header_t * header = &name.header; \
lv_draw_buf_init(&name, header->w, header->h, (lv_color_format_t)header->cf, header->stride, buf_##name, sizeof(buf_##name)); \
lv_draw_buf_set_flag(&name, LV_IMAGE_FLAGS_MODIFIABLE); \
} while(0)
/**********************
* TYPEDEFS
**********************/
typedef void * (*lv_draw_buf_malloc_cb)(size_t size, lv_color_format_t color_format);
typedef void (*lv_draw_buf_free_cb)(void * draw_buf);
typedef void * (*lv_draw_buf_align_cb)(void * buf, lv_color_format_t color_format);
typedef void (*lv_draw_buf_cache_operation_cb)(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
typedef uint32_t (*lv_draw_buf_width_to_stride_cb)(uint32_t w, lv_color_format_t color_format);
struct lv_draw_buf_t {
lv_image_header_t header;
uint32_t data_size; /**< Total buf size in bytes */
uint8_t * data;
void * unaligned_data; /**< Unaligned address of `data`, used internally by lvgl */
const lv_draw_buf_handlers_t * handlers; /**< draw buffer alloc/free ops. */
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize the draw buffer with the default handlers.
*
* @param handlers the draw buffer handlers to set
*/
void lv_draw_buf_init_with_default_handlers(lv_draw_buf_handlers_t * handlers);
/**
* Initialize the draw buffer with given handlers.
*
* @param handlers the draw buffer handlers to set
* @param buf_malloc_cb the callback to allocate memory for the buffer
* @param buf_free_cb the callback to free memory of the buffer
* @param align_pointer_cb the callback to align the buffer
* @param invalidate_cache_cb the callback to invalidate the cache of the buffer
* @param flush_cache_cb the callback to flush buffer
* @param width_to_stride_cb the callback to calculate the stride based on the width and color format
*/
void lv_draw_buf_handlers_init(lv_draw_buf_handlers_t * handlers,
lv_draw_buf_malloc_cb buf_malloc_cb,
lv_draw_buf_free_cb buf_free_cb,
lv_draw_buf_align_cb align_pointer_cb,
lv_draw_buf_cache_operation_cb invalidate_cache_cb,
lv_draw_buf_cache_operation_cb flush_cache_cb,
lv_draw_buf_width_to_stride_cb width_to_stride_cb);
/**
* Get the struct which holds the callbacks for draw buf management.
* Custom callback can be set on the returned value
* @return pointer to the struct of handlers
*/
lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void);
lv_draw_buf_handlers_t * lv_draw_buf_get_font_handlers(void);
lv_draw_buf_handlers_t * lv_draw_buf_get_image_handlers(void);
/**
* Align the address of a buffer. The buffer needs to be large enough for the real data after alignment
* @param buf the data to align
* @param color_format the color format of the buffer
* @return the aligned buffer
*/
void * lv_draw_buf_align(void * buf, lv_color_format_t color_format);
/**
* Align the address of a buffer with custom draw buffer handlers.
* The buffer needs to be large enough for the real data after alignment
* @param handlers the draw buffer handlers
* @param buf the data to align
* @param color_format the color format of the buffer
* @return the aligned buffer
*/
void * lv_draw_buf_align_ex(const lv_draw_buf_handlers_t * handlers, void * buf, lv_color_format_t color_format);
/**
* Invalidate the cache of the buffer
* @param draw_buf the draw buffer needs to be invalidated
* @param area the area to invalidate in the buffer,
* use NULL to invalidate the whole draw buffer address range
*/
void lv_draw_buf_invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
/**
* Flush the cache of the buffer
* @param draw_buf the draw buffer needs to be flushed
* @param area the area to flush in the buffer,
* use NULL to flush the whole draw buffer address range
*/
void lv_draw_buf_flush_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
/**
* Calculate the stride in bytes based on a width and color format
* @param w the width in pixels
* @param color_format the color format
* @return the stride in bytes
*/
uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format);
/**
* Calculate the stride in bytes based on a width and color format
* @param handlers the draw buffer handlers
* @param w the width in pixels
* @param color_format the color format
* @return the stride in bytes
*/
uint32_t lv_draw_buf_width_to_stride_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w,
lv_color_format_t color_format);
/**
* Clear an area on the buffer
* @param draw_buf pointer to draw buffer
* @param a the area to clear, or NULL to clear the whole buffer
*/
void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a);
/**
* Copy an area from a buffer to another
* @param dest pointer to the destination draw buffer
* @param dest_area the area to copy from the destination buffer, if NULL, use the whole buffer
* @param src pointer to the source draw buffer
* @param src_area the area to copy from the destination buffer, if NULL, use the whole buffer
* @note `dest_area` and `src_area` should have the same width and height
* @note `dest` and `src` should have same color format. Color converting is not supported fow now.
*/
void lv_draw_buf_copy(lv_draw_buf_t * dest, const lv_area_t * dest_area,
const lv_draw_buf_t * src, const lv_area_t * src_area);
/**
* Note: Eventually, lv_draw_buf_malloc/free will be kept as private.
* For now, we use `create` to distinguish with malloc.
*
* Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it
* that meets specified requirements.
*
* @param w the buffer width in pixels
* @param h the buffer height in pixels
* @param cf the color format for image
* @param stride the stride in bytes for image. Use 0 for automatic calculation based on
* w, cf, and global stride alignment configuration.
*/
lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride);
/**
* Note: Eventually, lv_draw_buf_malloc/free will be kept as private.
* For now, we use `create` to distinguish with malloc.
*
* Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it
* that meets specified requirements.
*
* @param handlers the draw buffer handlers
* @param w the buffer width in pixels
* @param h the buffer height in pixels
* @param cf the color format for image
* @param stride the stride in bytes for image. Use 0 for automatic calculation based on
* w, cf, and global stride alignment configuration.
*/
lv_draw_buf_t * lv_draw_buf_create_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w, uint32_t h,
lv_color_format_t cf, uint32_t stride);
/**
* Duplicate a draw buf with same image size, stride and color format. Copy the image data too.
* @param draw_buf the draw buf to duplicate
* @return the duplicated draw buf on success, NULL if failed
*/
lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf);
/**
* Duplicate a draw buf with same image size, stride and color format. Copy the image data too.
* @param handlers the draw buffer handlers
* @param draw_buf the draw buf to duplicate
* @return the duplicated draw buf on success, NULL if failed
*/
lv_draw_buf_t * lv_draw_buf_dup_ex(const lv_draw_buf_handlers_t * handlers, const lv_draw_buf_t * draw_buf);
/**
* Initialize a draw buf with the given buffer and parameters. Clear draw buffer flag to zero.
* @param draw_buf the draw buf to initialize
* @param w the buffer width in pixels
* @param h the buffer height in pixels
* @param cf the color format
* @param stride the stride in bytes. Use 0 for automatic calculation
* @param data the buffer used for drawing. Unaligned `data` will be aligned internally
* @param data_size the size of the buffer in bytes
* @return return LV_RESULT_OK on success, LV_RESULT_INVALID otherwise
*/
lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride,
void * data, uint32_t data_size);
/**
* Keep using the existing memory, reshape the draw buffer to the given width and height.
* Return NULL if data_size is smaller than the required size.
* @param draw_buf pointer to a draw buffer
* @param cf the new color format, use 0 or LV_COLOR_FORMAT_UNKNOWN to keep using the original color format.
* @param w the new width in pixels
* @param h the new height in pixels
* @param stride the stride in bytes for image. Use 0 for automatic calculation.
*/
lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t cf, uint32_t w, uint32_t h,
uint32_t stride);
/**
* Destroy a draw buf by freeing the actual buffer if it's marked as LV_IMAGE_FLAGS_ALLOCATED in header.
* Then free the lv_draw_buf_t struct.
*
* @param draw_buf the draw buffer to destroy
*/
void lv_draw_buf_destroy(lv_draw_buf_t * draw_buf);
/**
* Return pointer to the buffer at the given coordinates
*/
void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y);
/**
* Adjust the stride of a draw buf in place.
* @param src pointer to a draw buffer
* @param stride the new stride in bytes for image. Use LV_STRIDE_AUTO for automatic calculation.
* @return LV_RESULT_OK: success or LV_RESULT_INVALID: failed
*/
lv_result_t lv_draw_buf_adjust_stride(lv_draw_buf_t * src, uint32_t stride);
/**
* Premultiply draw buffer color with alpha channel.
* If it's already premultiplied, return directly.
* Only color formats with alpha channel will be processed.
*
* @return LV_RESULT_OK: premultiply success
*/
lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf);
bool lv_draw_buf_has_flag(const lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
void lv_draw_buf_set_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
void lv_draw_buf_clear_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
/**
* As of now, draw buf share same definition as `lv_image_dsc_t`.
* And is interchangeable with `lv_image_dsc_t`.
*/
void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img);
void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img);
/**
* Set the palette color of an indexed image. Valid only for `LV_COLOR_FORMAT_I1/2/4/8`
* @param draw_buf pointer to an image descriptor
* @param index the palette color to set:
* - for `LV_COLOR_FORMAT_I1`: 0..1
* - for `LV_COLOR_FORMAT_I2`: 0..3
* - for `LV_COLOR_FORMAT_I4`: 0..15
* - for `LV_COLOR_FORMAT_I8`: 0..255
* @param color the color to set in lv_color32_t format
*/
void lv_draw_buf_set_palette(lv_draw_buf_t * draw_buf, uint8_t index, lv_color32_t color);
/**
* @deprecated Use lv_draw_buf_set_palette instead.
*/
void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c);
/**
* @deprecated Use lv_draw_buffer_create/destroy instead.
* Free the data pointer and dsc struct of an image.
*/
void lv_image_buf_free(lv_image_dsc_t * dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_BUF_H*/

View File

@@ -1,53 +0,0 @@
/**
* @file lv_draw_buf_private.h
*
*/
#ifndef LV_DRAW_BUF_PRIVATE_H
#define LV_DRAW_BUF_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_buf.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct lv_draw_buf_handlers_t {
lv_draw_buf_malloc_cb buf_malloc_cb;
lv_draw_buf_free_cb buf_free_cb;
lv_draw_buf_align_cb align_pointer_cb;
lv_draw_buf_cache_operation_cb invalidate_cache_cb;
lv_draw_buf_cache_operation_cb flush_cache_cb;
lv_draw_buf_width_to_stride_cb width_to_stride_cb;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Called internally to initialize the draw_buf_handlers in lv_global
*/
void lv_draw_buf_init_handlers(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_BUF_PRIVATE_H*/

View File

@@ -1,314 +0,0 @@
/**
* @file lv_draw_img.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_image_private.h"
#include "../misc/lv_area_private.h"
#include "lv_image_decoder_private.h"
#include "lv_draw_private.h"
#include "../display/lv_display.h"
#include "../misc/lv_log.h"
#include "../misc/lv_math.h"
#include "../core/lv_refr.h"
#include "../stdlib/lv_mem.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
lv_image_decoder_dsc_t * decoder_dsc, lv_area_t * relative_decoded_area,
const lv_area_t * img_area, const lv_area_t * clipped_img_area,
lv_draw_image_core_cb draw_core_cb);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_image_dsc_t));
dsc->recolor = lv_color_black();
dsc->opa = LV_OPA_COVER;
dsc->scale_x = LV_SCALE_NONE;
dsc->scale_y = LV_SCALE_NONE;
dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
dsc->image_area.x2 = LV_COORD_MIN; /*Indicate invalid area by default by setting a negative size*/
dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t);
}
lv_draw_image_dsc_t * lv_draw_task_get_image_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_IMAGE ? (lv_draw_image_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->scale_x <= 0 || dsc->scale_y <= 0) {
/* NOT draw if scale is negative or zero */
return;
}
lv_draw_task_t * t = lv_draw_add_task(layer, coords);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_LAYER;
t->state = LV_DRAW_TASK_STATE_WAITING;
lv_image_buf_get_transformed_area(&t->_real_area, lv_area_get_width(coords), lv_area_get_height(coords),
dsc->rotation, dsc->scale_x, dsc->scale_y, &dsc->pivot);
lv_area_move(&t->_real_area, coords->x1, coords->y1);
lv_layer_t * layer_to_draw = (lv_layer_t *)dsc->src;
layer_to_draw->all_tasks_added = true;
lv_draw_finalize_task_creation(layer, t);
}
void lv_draw_image(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->src == NULL) {
LV_LOG_WARN("Image draw: src is NULL");
return;
}
if(dsc->opa <= LV_OPA_MIN) return;
if(dsc->scale_x <= 0 || dsc->scale_y <= 0) {
/* NOT draw if scale is negative or zero */
return;
}
LV_PROFILER_BEGIN;
lv_draw_image_dsc_t * new_image_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(new_image_dsc, dsc, sizeof(*dsc));
lv_result_t res = lv_image_decoder_get_info(new_image_dsc->src, &new_image_dsc->header);
if(res != LV_RESULT_OK) {
LV_LOG_WARN("Couldn't get info about the image");
lv_free(new_image_dsc);
return;
}
lv_draw_task_t * t = lv_draw_add_task(layer, coords);
t->draw_dsc = new_image_dsc;
t->type = LV_DRAW_TASK_TYPE_IMAGE;
lv_image_buf_get_transformed_area(&t->_real_area, lv_area_get_width(coords), lv_area_get_height(coords),
dsc->rotation, dsc->scale_x, dsc->scale_y, &dsc->pivot);
lv_area_move(&t->_real_area, coords->x1, coords->y1);
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
lv_image_src_t lv_image_src_get_type(const void * src)
{
if(src == NULL) return LV_IMAGE_SRC_UNKNOWN;
const uint8_t * u8_p = src;
/*The first byte shows the type of the image source*/
if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) {
return LV_IMAGE_SRC_FILE; /*If it's an ASCII character then it's file name*/
}
else if(u8_p[0] >= 0x80) {
return LV_IMAGE_SRC_SYMBOL; /*Symbols begins after 0x7F*/
}
else {
return LV_IMAGE_SRC_VARIABLE; /*`lv_image_dsc_t` is draw to the first byte < 0x20*/
}
}
void lv_draw_image_normal_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb)
{
if(draw_core_cb == NULL) {
LV_LOG_WARN("draw_core_cb is NULL");
return;
}
lv_area_t draw_area;
lv_area_copy(&draw_area, coords);
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
int32_t w = lv_area_get_width(coords);
int32_t h = lv_area_get_height(coords);
lv_image_buf_get_transformed_area(&draw_area, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
&draw_dsc->pivot);
draw_area.x1 += coords->x1;
draw_area.y1 += coords->y1;
draw_area.x2 += coords->x1;
draw_area.y2 += coords->y1;
}
lv_area_t clipped_img_area;
if(!lv_area_intersect(&clipped_img_area, &draw_area, draw_unit->clip_area)) {
return;
}
lv_image_decoder_dsc_t decoder_dsc;
lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Failed to open image");
return;
}
img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, NULL, coords, &clipped_img_area, draw_core_cb);
lv_image_decoder_close(&decoder_dsc);
}
void lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb)
{
if(draw_core_cb == NULL) {
LV_LOG_WARN("draw_core_cb is NULL");
return;
}
lv_image_decoder_dsc_t decoder_dsc;
lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL);
if(res != LV_RESULT_OK) {
LV_LOG_ERROR("Failed to open image");
return;
}
int32_t img_w = draw_dsc->header.w;
int32_t img_h = draw_dsc->header.h;
lv_area_t tile_area;
if(lv_area_get_width(&draw_dsc->image_area) >= 0) {
tile_area = draw_dsc->image_area;
}
else {
tile_area = *coords;
}
lv_area_set_width(&tile_area, img_w);
lv_area_set_height(&tile_area, img_h);
int32_t tile_x_start = tile_area.x1;
lv_area_t relative_decoded_area = {
.x1 = LV_COORD_MIN,
.y1 = LV_COORD_MIN,
.x2 = LV_COORD_MIN,
.y2 = LV_COORD_MIN,
};
while(tile_area.y1 <= coords->y2) {
while(tile_area.x1 <= coords->x2) {
lv_area_t clipped_img_area;
if(lv_area_intersect(&clipped_img_area, &tile_area, coords)) {
img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, &relative_decoded_area, &tile_area, &clipped_img_area,
draw_core_cb);
}
tile_area.x1 += img_w;
tile_area.x2 += img_w;
}
tile_area.y1 += img_h;
tile_area.y2 += img_h;
tile_area.x1 = tile_x_start;
tile_area.x2 = tile_x_start + img_w - 1;
}
lv_image_decoder_close(&decoder_dsc);
}
void lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle,
uint16_t scale_x, uint16_t scale_y, const lv_point_t * pivot)
{
if(angle == 0 && scale_x == LV_SCALE_NONE && scale_y == LV_SCALE_NONE) {
res->x1 = 0;
res->y1 = 0;
res->x2 = w - 1;
res->y2 = h - 1;
return;
}
lv_point_t p[4] = {
{0, 0},
{w, 0},
{0, h},
{w, h},
};
lv_point_transform(&p[0], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[1], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[2], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[3], angle, scale_x, scale_y, pivot, true);
res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x);
res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) - 1;
res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y);
res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) - 1;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
lv_image_decoder_dsc_t * decoder_dsc, lv_area_t * relative_decoded_area,
const lv_area_t * img_area, const lv_area_t * clipped_img_area,
lv_draw_image_core_cb draw_core_cb)
{
lv_draw_image_sup_t sup;
sup.alpha_color = draw_dsc->recolor;
sup.palette = decoder_dsc->palette;
sup.palette_size = decoder_dsc->palette_size;
/*The whole image is available, just draw it*/
if(decoder_dsc->decoded && (relative_decoded_area == NULL || relative_decoded_area->x1 == LV_COORD_MIN)) {
draw_core_cb(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area);
}
/*Draw in smaller pieces*/
else {
lv_area_t relative_full_area_to_decode = *clipped_img_area;
lv_area_move(&relative_full_area_to_decode, -img_area->x1, -img_area->y1);
lv_area_t tmp;
if(relative_decoded_area == NULL) relative_decoded_area = &tmp;
relative_decoded_area->x1 = LV_COORD_MIN;
relative_decoded_area->y1 = LV_COORD_MIN;
relative_decoded_area->x2 = LV_COORD_MIN;
relative_decoded_area->y2 = LV_COORD_MIN;
lv_result_t res = LV_RESULT_OK;
while(res == LV_RESULT_OK) {
res = lv_image_decoder_get_area(decoder_dsc, &relative_full_area_to_decode, relative_decoded_area);
lv_area_t absolute_decoded_area = *relative_decoded_area;
lv_area_move(&absolute_decoded_area, img_area->x1, img_area->y1);
if(res == LV_RESULT_OK) {
/*Limit draw area to the current decoded area and draw the image*/
lv_area_t clipped_img_area_sub;
if(lv_area_intersect(&clipped_img_area_sub, clipped_img_area, &absolute_decoded_area)) {
draw_core_cb(draw_unit, draw_dsc, decoder_dsc, &sup,
&absolute_decoded_area, &clipped_img_area_sub);
}
}
}
}
}

View File

@@ -1,129 +0,0 @@
/**
* @file lv_draw_image.h
*
*/
#ifndef LV_DRAW_IMAGE_H
#define LV_DRAW_IMAGE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw.h"
#include "lv_image_decoder.h"
#include "lv_draw_buf.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* MACROS
**********************/
typedef struct lv_draw_image_dsc_t {
lv_draw_dsc_base_t base;
const void * src;
lv_image_header_t header;
int32_t rotation;
int32_t scale_x;
int32_t scale_y;
int32_t skew_x;
int32_t skew_y;
lv_point_t pivot;
lv_color_t recolor;
lv_opa_t recolor_opa;
lv_opa_t opa;
lv_blend_mode_t blend_mode : 4;
uint16_t antialias : 1;
uint16_t tile : 1;
lv_draw_image_sup_t * sup;
/** Used to indicate the entire original, non-clipped area where the image is to be drawn.
* This is important for:
* 1. Layer rendering, where it might happen that only a smaller area of the layer is rendered.
* 2. Tiled images, where the target draw area is larger than the image to be tiled.
*/
lv_area_t image_area;
int32_t clip_radius;
const lv_image_dsc_t * bitmap_mask_src;
} lv_draw_image_dsc_t;
/**
* PErform the actual rendering of a decoded image
* @param draw_unit pointer to a draw unit
* @param draw_dsc the draw descriptor of the image
* @param decoder_dsc pointer to the decoded image's descriptor
* @param sup supplementary data
* @param img_coords the absolute coordinates of the image
* @param clipped_img_area the absolute clip coordinates
*/
typedef void (*lv_draw_image_core_cb)(lv_draw_unit_t * draw_unit, 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);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize an image draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc);
/**
* Try to get an image draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_IMAGE
*/
lv_draw_image_dsc_t * lv_draw_task_get_image_dsc(lv_draw_task_t * task);
/**
* Create an image draw task
* @param layer pointer to a layer
* @param dsc pointer to an initialized draw descriptor
* @param coords the coordinates of the image
* @note `coords` can be small than the real image area
* (if only a part of the image is rendered)
* or can be larger (in case of tiled images). .
*/
void lv_draw_image(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords);
/**
* Create a draw task to blend a layer to another layer
* @param layer pointer to a layer
* @param dsc pointer to an initialized draw descriptor
* @param coords the coordinates of the layer.
* @note `coords` can be small than the total widget area from which the layer is created
* (if only a part of the widget was rendered to a layer)
*/
void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords);
/**
* Get the type of an image source
* @param src pointer to an image source:
* - pointer to an 'lv_image_t' variable (image stored internally and compiled into the code)
* - a path to a file (e.g. "S:/folder/image.bin")
* - or a symbol (e.g. LV_SYMBOL_CLOSE)
* @return type of the image source LV_IMAGE_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
*/
lv_image_src_t lv_image_src_get_type(const void * src);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_IMAGE_H*/

View File

@@ -1,85 +0,0 @@
/**
* @file lv_draw_image_private.h
*
*/
#ifndef LV_DRAW_IMAGE_PRIVATE_H
#define LV_DRAW_IMAGE_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_image.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* TYPEDEFS
**********************/
struct lv_draw_image_sup_t {
lv_color_t alpha_color;
const lv_color32_t * palette;
uint32_t palette_size : 9;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Can be used by draw units to handle the decoding and
* prepare everything for the actual image rendering
* @param draw_unit pointer to a draw unit
* @param draw_dsc the draw descriptor of the image
* @param coords the absolute coordinates of the image
* @param draw_core_cb a callback to perform the actual rendering
*/
void lv_draw_image_normal_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb);
/**
* Can be used by draw units for TILED images to handle the decoding and
* prepare everything for the actual image rendering
* @param draw_unit pointer to a draw unit
* @param draw_dsc the draw descriptor of the image
* @param coords the absolute coordinates of the image
* @param draw_core_cb a callback to perform the actual rendering
*/
void lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb);
/**
* Get the area of a rectangle if its rotated and scaled
* @param res store the coordinates here
* @param w width of the rectangle to transform
* @param h height of the rectangle to transform
* @param angle angle of rotation
* @param scale_x zoom in x direction, (256 no zoom)
* @param scale_y zoom in y direction, (256 no zoom)
* @param pivot x,y pivot coordinates of rotation
*/
void lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle,
uint16_t scale_x, uint16_t scale_y, const lv_point_t * pivot);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_IMAGE_PRIVATE_H*/

View File

@@ -1,446 +0,0 @@
/**
* @file lv_draw_label.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_label_private.h"
#include "lv_draw_private.h"
#include "../misc/lv_area_private.h"
#include "lv_draw_vector_private.h"
#include "lv_draw_rect_private.h"
#include "../core/lv_obj.h"
#include "../misc/lv_math.h"
#include "../core/lv_obj_event.h"
#include "../misc/lv_bidi_private.h"
#include "../misc/lv_text_private.h"
#include "../misc/lv_assert.h"
#include "../stdlib/lv_mem.h"
#include "../stdlib/lv_string.h"
#include "../core/lv_global.h"
/*********************
* DEFINES
*********************/
#define LABEL_RECOLOR_PAR_LENGTH 6
#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/
#define font_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->font_draw_buf_handlers)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_label_dsc_t));
dsc->opa = LV_OPA_COVER;
dsc->color = lv_color_black();
dsc->font = LV_FONT_DEFAULT;
dsc->sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
dsc->sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
dsc->sel_color = lv_color_black();
dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE);
dsc->bidi_dir = LV_BASE_DIR_LTR;
dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t);
}
lv_draw_label_dsc_t * lv_draw_task_get_label_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_LABEL ? (lv_draw_label_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_glyph_dsc_init(lv_draw_glyph_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_glyph_dsc_t));
}
void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_layer_t * layer, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= LV_OPA_MIN) return;
if(dsc->text == NULL || dsc->text[0] == '\0') return;
if(dsc->font == NULL) {
LV_LOG_WARN("dsc->font == NULL");
return;
}
LV_PROFILER_BEGIN;
lv_draw_task_t * t = lv_draw_add_task(layer, coords);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_LABEL;
/*The text is stored in a local variable so malloc memory for it*/
if(dsc->text_local) {
lv_draw_label_dsc_t * new_dsc = t->draw_dsc;
new_dsc->text = lv_strdup(dsc->text);
}
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
void LV_ATTRIBUTE_FAST_MEM lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc,
const lv_point_t * point, uint32_t unicode_letter)
{
if(dsc->opa <= LV_OPA_MIN) return;
if(dsc->font == NULL) {
LV_LOG_WARN("dsc->font == NULL");
return;
}
if(lv_text_is_marker(unicode_letter)) return;
LV_PROFILER_BEGIN;
lv_font_glyph_dsc_t g;
lv_font_get_glyph_dsc(dsc->font, &g, unicode_letter, 0);
lv_area_t a;
a.x1 = point->x;
a.y1 = point->y;
a.x2 = a.x1 + g.adv_w;
a.y2 = a.y1 + lv_font_get_line_height(g.resolved_font ? g.resolved_font : dsc->font);
/*lv_draw_label needs UTF8 text so convert the Unicode character to an UTF8 string */
uint32_t letter_buf[2];
letter_buf[0] = lv_text_unicode_to_encoded(unicode_letter);
letter_buf[1] = '\0';
const char * letter_buf_char = (const char *)letter_buf;
#if LV_BIG_ENDIAN_SYSTEM
while(*letter_buf_char == 0) ++letter_buf_char;
#endif
dsc->text = letter_buf_char;
dsc->text_local = 1;
lv_draw_label(layer, dsc, &a);
LV_PROFILER_END;
}
void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords,
lv_draw_glyph_cb_t cb)
{
const lv_font_t * font = dsc->font;
int32_t w;
lv_area_t clipped_area;
bool clip_ok = lv_area_intersect(&clipped_area, coords, draw_unit->clip_area);
if(!clip_ok) return;
lv_text_align_t align = dsc->align;
lv_base_dir_t base_dir = dsc->bidi_dir;
lv_bidi_calculate_align(&align, &base_dir, dsc->text);
if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) {
/*Normally use the label's width as width*/
w = lv_area_get_width(coords);
}
else {
/*If EXPAND is enabled then not limit the text's width to the object's width*/
lv_point_t p;
lv_text_get_size(&p, dsc->text, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX,
dsc->flag);
w = p.x;
}
int32_t line_height_font = lv_font_get_line_height(font);
int32_t line_height = line_height_font + dsc->line_space;
/*Init variables for the first line*/
int32_t line_width = 0;
lv_point_t pos;
lv_point_set(&pos, coords->x1, coords->y1);
int32_t x_ofs = 0;
int32_t y_ofs = 0;
x_ofs = dsc->ofs_x;
y_ofs = dsc->ofs_y;
pos.y += y_ofs;
uint32_t line_start = 0;
int32_t last_line_start = -1;
/*Check the hint to use the cached info*/
if(dsc->hint && y_ofs == 0 && coords->y1 < 0) {
/*If the label changed too much recalculate the hint.*/
if(LV_ABS(dsc->hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) {
dsc->hint->line_start = -1;
}
last_line_start = dsc->hint->line_start;
}
/*Use the hint if it's valid*/
if(dsc->hint && last_line_start >= 0) {
line_start = last_line_start;
pos.y += dsc->hint->y;
}
uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL,
dsc->flag);
/*Go the first visible line*/
while(pos.y + line_height_font < draw_unit->clip_area->y1) {
/*Go to next line*/
line_start = line_end;
line_end += lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
pos.y += line_height;
/*Save at the threshold coordinate*/
if(dsc->hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && dsc->hint->line_start < 0) {
dsc->hint->line_start = line_start;
dsc->hint->y = pos.y - coords->y1;
dsc->hint->coord_y = coords->y1;
}
if(dsc->text[line_start] == '\0') return;
}
/*Align to middle*/
if(align == LV_TEXT_ALIGN_CENTER) {
line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space);
pos.x += (lv_area_get_width(coords) - line_width) / 2;
}
/*Align to the right*/
else if(align == LV_TEXT_ALIGN_RIGHT) {
line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space);
pos.x += lv_area_get_width(coords) - line_width;
}
uint32_t sel_start = dsc->sel_start;
uint32_t sel_end = dsc->sel_end;
if(sel_start > sel_end) {
uint32_t tmp = sel_start;
sel_start = sel_end;
sel_end = tmp;
}
lv_area_t bg_coords;
lv_draw_glyph_dsc_t draw_letter_dsc;
lv_draw_glyph_dsc_init(&draw_letter_dsc);
draw_letter_dsc.opa = dsc->opa;
draw_letter_dsc.bg_coords = &bg_coords;
draw_letter_dsc.color = dsc->color;
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.opa = dsc->opa;
int32_t underline_width = font->underline_thickness ? font->underline_thickness : 1;
int32_t line_start_x;
uint32_t i;
int32_t letter_w;
/*Write out all lines*/
while(dsc->text[line_start] != '\0') {
pos.x += x_ofs;
line_start_x = pos.x;
/*Write all letter of a line*/
i = 0;
#if LV_USE_BIDI
char * bidi_txt = lv_malloc(line_end - line_start + 1);
LV_ASSERT_MALLOC(bidi_txt);
lv_bidi_process_paragraph(dsc->text + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0);
#else
const char * bidi_txt = dsc->text + line_start;
#endif
while(i < line_end - line_start) {
uint32_t logical_char_pos = 0;
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
#if LV_USE_BIDI
logical_char_pos = lv_text_encoded_get_char_id(dsc->text, line_start);
uint32_t t = lv_text_encoded_get_char_id(bidi_txt, i);
logical_char_pos += lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL);
#else
logical_char_pos = lv_text_encoded_get_char_id(dsc->text, line_start + i);
#endif
}
uint32_t letter;
uint32_t letter_next;
lv_text_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i);
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
/*Always set the bg_coordinates for placeholder drawing*/
bg_coords.x1 = pos.x;
bg_coords.y1 = pos.y;
bg_coords.x2 = pos.x + letter_w - 1;
bg_coords.y2 = pos.y + line_height - 1;
if(i >= line_end - line_start) {
if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) {
lv_area_t fill_area;
fill_area.x1 = line_start_x;
fill_area.x2 = pos.x + letter_w - 1;
fill_area.y1 = pos.y + font->line_height - font->base_line - font->underline_position;
fill_area.y2 = fill_area.y1 + underline_width - 1;
fill_dsc.color = dsc->color;
cb(draw_unit, NULL, &fill_dsc, &fill_area);
}
if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) {
lv_area_t fill_area;
fill_area.x1 = line_start_x;
fill_area.x2 = pos.x + letter_w - 1;
fill_area.y1 = pos.y + (font->line_height - font->base_line) * 2 / 3 + font->underline_thickness / 2;
fill_area.y2 = fill_area.y1 + underline_width - 1;
fill_dsc.color = dsc->color;
cb(draw_unit, NULL, &fill_dsc, &fill_area);
}
}
if(sel_start != 0xFFFF && sel_end != 0xFFFF && logical_char_pos >= sel_start && logical_char_pos < sel_end) {
draw_letter_dsc.color = dsc->sel_color;
fill_dsc.color = dsc->sel_bg_color;
cb(draw_unit, NULL, &fill_dsc, &bg_coords);
}
else {
draw_letter_dsc.color = dsc->color;
}
draw_letter(draw_unit, &draw_letter_dsc, &pos, font, letter, cb);
if(letter_w > 0) {
pos.x += letter_w + dsc->letter_space;
}
}
#if LV_USE_BIDI
lv_free(bidi_txt);
bidi_txt = NULL;
#endif
/*Go to next line*/
line_start = line_end;
line_end += lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
pos.x = coords->x1;
/*Align to middle*/
if(align == LV_TEXT_ALIGN_CENTER) {
line_width =
lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space);
pos.x += (lv_area_get_width(coords) - line_width) / 2;
}
/*Align to the right*/
else if(align == LV_TEXT_ALIGN_RIGHT) {
line_width =
lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space);
pos.x += lv_area_get_width(coords) - line_width;
}
/*Go the next line position*/
pos.y += line_height;
if(pos.y > draw_unit->clip_area->y2) break;
}
if(draw_letter_dsc._draw_buf) lv_draw_buf_destroy(draw_letter_dsc._draw_buf);
LV_ASSERT_MEM_INTEGRITY();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos,
const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb)
{
lv_font_glyph_dsc_t g;
if(lv_text_is_marker(letter)) /*Markers are valid letters but should not be rendered.*/
return;
LV_PROFILER_BEGIN;
bool g_ret = lv_font_get_glyph_dsc(font, &g, letter, '\0');
if(g_ret == false) {
/*Add warning if the dsc is not found*/
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter);
}
/*Don't draw anything if the character is empty. E.g. space*/
if((g.box_h == 0) || (g.box_w == 0)) {
LV_PROFILER_END;
return;
}
lv_area_t letter_coords;
letter_coords.x1 = pos->x + g.ofs_x;
letter_coords.x2 = letter_coords.x1 + g.box_w - 1;
letter_coords.y1 = pos->y + (font->line_height - font->base_line) - g.box_h - g.ofs_y;
letter_coords.y2 = letter_coords.y1 + g.box_h - 1;
/*If the letter is completely out of mask don't draw it*/
if(lv_area_is_out(&letter_coords, draw_unit->clip_area, 0) &&
lv_area_is_out(dsc->bg_coords, draw_unit->clip_area, 0)) {
LV_PROFILER_END;
return;
}
if(g.resolved_font) {
lv_draw_buf_t * draw_buf = NULL;
if(LV_FONT_GLYPH_FORMAT_NONE < g.format && g.format < LV_FONT_GLYPH_FORMAT_IMAGE) {
/*Only check draw buf for bitmap glyph*/
draw_buf = lv_draw_buf_reshape(dsc->_draw_buf, 0, g.box_w, g.box_h, LV_STRIDE_AUTO);
if(draw_buf == NULL) {
if(dsc->_draw_buf) lv_draw_buf_destroy(dsc->_draw_buf);
uint32_t h = g.box_h;
if(h * g.box_w < 64) h *= 2; /*Alloc a slightly larger buffer*/
draw_buf = lv_draw_buf_create_ex(font_draw_buf_handlers, g.box_w, h, LV_COLOR_FORMAT_A8, LV_STRIDE_AUTO);
LV_ASSERT_MALLOC(draw_buf);
draw_buf->header.h = g.box_h;
dsc->_draw_buf = draw_buf;
}
}
dsc->glyph_data = (void *) lv_font_get_glyph_bitmap(&g, draw_buf);
dsc->format = dsc->glyph_data ? g.format : LV_FONT_GLYPH_FORMAT_NONE;
}
else {
dsc->format = LV_FONT_GLYPH_FORMAT_NONE;
}
dsc->letter_coords = &letter_coords;
dsc->g = &g;
cb(draw_unit, dsc, NULL, NULL);
lv_font_glyph_release_draw_data(&g);
LV_PROFILER_END;
}

View File

@@ -1,140 +0,0 @@
/**
* @file lv_draw_label.h
*
*/
#ifndef LV_DRAW_LABEL_H
#define LV_DRAW_LABEL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw.h"
#include "lv_draw_rect.h"
#include "../misc/lv_bidi.h"
#include "../misc/lv_text.h"
#include "../misc/lv_color.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
const char * text;
const lv_font_t * font;
uint32_t sel_start;
uint32_t sel_end;
lv_color_t color;
lv_color_t sel_color;
lv_color_t sel_bg_color;
int32_t line_space;
int32_t letter_space;
int32_t ofs_x;
int32_t ofs_y;
lv_opa_t opa;
lv_base_dir_t bidi_dir;
lv_text_align_t align;
lv_text_flag_t flag;
lv_text_decor_t decor : 3;
lv_blend_mode_t blend_mode : 3;
/**
* < 1: malloc buffer and copy `text` there.
* 0: `text` is const and it's pointer will be valid during rendering.*/
uint8_t text_local : 1;
lv_draw_label_hint_t * hint;
} lv_draw_label_dsc_t;
/**
* Passed as a parameter to `lv_draw_label_iterate_characters` to
* draw the characters one by one
* @param draw_unit pointer to a draw unit
* @param dsc pointer to `lv_draw_glyph_dsc_t` to describe the character to draw
* if NULL don't draw character
* @param fill_dsc pointer to a fill descriptor to draw a background for the character or
* underline or strike through
* if NULL do not fill anything
* @param fill_area the area to fill
* if NULL do not fill anything
*/
typedef void(*lv_draw_glyph_cb_t)(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, lv_draw_fill_dsc_t * fill_dsc,
const lv_area_t * fill_area);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a label draw descriptor
* @param dsc pointer to a draw descriptor
*/
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc);
/**
* Try to get a label draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_LABEL
*/
lv_draw_label_dsc_t * lv_draw_task_get_label_dsc(lv_draw_task_t * task);
/**
* Initialize a glyph draw descriptor.
* Used internally.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_glyph_dsc_init(lv_draw_glyph_dsc_t * dsc);
/**
* Crate a draw task to render a text
* @param layer pointer to a layer
* @param dsc pointer to draw descriptor
* @param coords coordinates of the character
*/
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_label(lv_layer_t * layer, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords);
/**
* Crate a draw task to render a single character
* @param layer pointer to a layer
* @param dsc pointer to draw descriptor
* @param point position of the label
* @param unicode_letter the letter to draw
*/
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc,
const lv_point_t * point, uint32_t unicode_letter);
/**
* Should be used during rendering the characters to get the position and other
* parameters of the characters
* @param draw_unit pointer to a draw unit
* @param dsc pointer to draw descriptor
* @param coords coordinates of the label
* @param cb a callback to call to draw each glyphs one by one
*/
void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords, lv_draw_glyph_cb_t cb);
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LABEL_H*/

View File

@@ -1,68 +0,0 @@
/**
* @file lv_draw_label_private.h
*
*/
#ifndef LV_DRAW_LABEL_PRIVATE_H
#define LV_DRAW_LABEL_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_label.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/** Store some info to speed up drawing of very large texts
* It takes a lot of time to get the first visible character because
* all the previous characters needs to be checked to calculate the positions.
* This structure stores an earlier (e.g. at -1000 px) coordinate and the index of that line.
* Therefore the calculations can start from here.*/
struct lv_draw_label_hint_t {
/** Index of the line at `y` coordinate*/
int32_t line_start;
/** Give the `y` coordinate of the first letter at `line start` index. Relative to the label's coordinates*/
int32_t y;
/** The 'y1' coordinate of the label when the hint was saved.
* Used to invalidate the hint if the label has moved too much.*/
int32_t coord_y;
};
struct lv_draw_glyph_dsc_t {
void * glyph_data; /**< Depends on `format` field, it could be image source or draw buf of bitmap or vector data. */
lv_font_glyph_format_t format;
const lv_area_t * letter_coords;
const lv_area_t * bg_coords;
const lv_font_glyph_dsc_t * g;
lv_color_t color;
lv_opa_t opa;
lv_draw_buf_t * _draw_buf; /**< a shared draw buf for get_bitmap, do not use it directly, use glyph_data instead */
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LABEL_PRIVATE_H*/

View File

@@ -1,77 +0,0 @@
/**
* @file lv_draw_line.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_private.h"
#include "../core/lv_refr.h"
#include "../misc/lv_math.h"
#include "../misc/lv_types.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void LV_ATTRIBUTE_FAST_MEM lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_line_dsc_t));
dsc->width = 1;
dsc->opa = LV_OPA_COVER;
dsc->color = lv_color_black();
dsc->base.dsc_size = sizeof(lv_draw_line_dsc_t);
}
lv_draw_line_dsc_t * lv_draw_task_get_line_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_LINE ? (lv_draw_line_dsc_t *)task->draw_dsc : NULL;
}
void LV_ATTRIBUTE_FAST_MEM lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc)
{
if(dsc->width == 0) return;
if(dsc->opa <= LV_OPA_MIN) return;
LV_PROFILER_BEGIN;
lv_area_t a;
a.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width;
a.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width;
a.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width;
a.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width;
lv_draw_task_t * t = lv_draw_add_task(layer, &a);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_LINE;
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,76 +0,0 @@
/**
* @file lv_draw_line.h
*
*/
#ifndef LV_DRAW_LINE_H
#define LV_DRAW_LINE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
lv_point_precise_t p1;
lv_point_precise_t p2;
lv_color_t color;
int32_t width;
int32_t dash_width;
int32_t dash_gap;
lv_opa_t opa;
lv_blend_mode_t blend_mode : 2;
uint8_t round_start : 1;
uint8_t round_end : 1;
uint8_t raw_end : 1; /**< Do not bother with perpendicular line ending if it's not visible for any reason */
} lv_draw_line_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a line draw descriptor
* @param dsc pointer to a draw descriptor
*/
void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc);
/**
* Try to get a line draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_LINE
*/
lv_draw_line_dsc_t * lv_draw_task_get_line_dsc(lv_draw_task_t * task);
/**
* Create a line draw task
* @param layer pointer to a layer
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
*/
void lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_LINE_H*/

View File

@@ -1,81 +0,0 @@
/**
* @file lv_draw_mask.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_mask_private.h"
#include "lv_draw_private.h"
#include "../core/lv_refr.h"
#include "../misc/lv_math.h"
#include "../misc/lv_types.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void LV_ATTRIBUTE_FAST_MEM lv_draw_mask_rect_dsc_init(lv_draw_mask_rect_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_mask_rect_dsc_t));
}
lv_draw_mask_rect_dsc_t * lv_draw_task_get_mask_rect_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_MASK_RECTANGLE ? (lv_draw_mask_rect_dsc_t *)task->draw_dsc : NULL;
}
void LV_ATTRIBUTE_FAST_MEM lv_draw_mask_rect(lv_layer_t * layer, const lv_draw_mask_rect_dsc_t * dsc)
{
if(!lv_color_format_has_alpha(layer->color_format)) {
LV_LOG_WARN("Only layers with alpha channel can be masked");
return;
}
LV_PROFILER_BEGIN;
lv_draw_task_t * t = lv_draw_add_task(layer, &layer->buf_area);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_MASK_RECTANGLE;
lv_draw_dsc_base_t * base_dsc = t->draw_dsc;
base_dsc->layer = layer;
if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) {
/*Disable sending LV_EVENT_DRAW_TASK_ADDED first to avoid triggering recursive
*event calls due draw task adds in the event*/
lv_obj_remove_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
lv_obj_send_event(dsc->base.obj, LV_EVENT_DRAW_TASK_ADDED, t);
lv_obj_add_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
}
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,56 +0,0 @@
/**
* @file lv_draw_mask.h
*
*/
#ifndef LV_DRAW_MASK_H
#define LV_DRAW_MASK_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
/*********************
* DEFINES
*********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a rectangle mask draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_rect_dsc_init(lv_draw_mask_rect_dsc_t * dsc);
/**
* Try to get a rectangle mask draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_MASK_RECTANGLE
*/
lv_draw_mask_rect_dsc_t * lv_draw_task_get_mask_rect_dsc(lv_draw_task_t * task);
/**
* Create a draw task to mask a rectangle from the buffer
* @param layer pointer to a layer
* @param dsc pointer to a draw descriptor
*/
void lv_draw_mask_rect(lv_layer_t * layer, const lv_draw_mask_rect_dsc_t * dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_MASK_H*/

View File

@@ -1,51 +0,0 @@
/**
* @file lv_draw_mask_private.h
*
*/
#ifndef LV_DRAW_MASK_PRIVATE_H
#define LV_DRAW_MASK_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_mask.h"
#include "lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* TYPEDEFS
**********************/
struct lv_draw_mask_rect_dsc_t {
lv_draw_dsc_base_t base;
lv_area_t area;
int32_t radius;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_MASK_PRIVATE_H*/

View File

@@ -1,196 +0,0 @@
/**
* @file lv_draw_private.h
*
*/
/**
* Modified by NXP in 2024
*/
#ifndef LV_DRAW_PRIVATE_H
#define LV_DRAW_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct lv_draw_task_t {
lv_draw_task_t * next;
lv_draw_task_type_t type;
/**
* The area where to draw
*/
lv_area_t area;
/**
* The real draw area. E.g. for shadow, outline, or transformed images it's different from `area`
*/
lv_area_t _real_area;
/** The original area which is updated*/
lv_area_t clip_area_original;
/**
* The clip area of the layer is saved here when the draw task is created.
* As the clip area of the layer can be changed as new draw tasks are added its current value needs to be saved.
* Therefore during drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks.
*/
lv_area_t clip_area;
#if LV_DRAW_TRANSFORM_USE_MATRIX
/** Transform matrix to be applied when rendering the layer */
lv_matrix_t matrix;
#endif
volatile int state; /** int instead of lv_draw_task_state_t to be sure its atomic */
void * draw_dsc;
/**
* The ID of the draw_unit which should take this task
*/
uint8_t preferred_draw_unit_id;
/**
* Set to which extent `preferred_draw_unit_id` is good at this task.
* 80: means 20% better (faster) than software rendering
* 100: the default value
* 110: means 10% worse (slower) than software rendering
*/
uint8_t preference_score;
};
struct lv_draw_mask_t {
void * user_data;
};
struct lv_draw_unit_t {
lv_draw_unit_t * next;
/**
* The target_layer on which drawing should happen
*/
lv_layer_t * target_layer;
const lv_area_t * clip_area;
/**
* Called to try to assign a draw task to itself.
* `lv_draw_get_next_available_task` can be used to get an independent draw task.
* A draw task should be assign only if the draw unit can draw it too
* @param draw_unit pointer to the draw unit
* @param layer pointer to a layer on which the draw task should be drawn
* @return >=0: The number of taken draw task:
* 0 means the task has not yet been completed.
* 1 means a new task has been accepted.
* -1: The draw unit wanted to work on a task but couldn't do that
* due to some errors (e.g. out of memory).
* It signals that LVGL should call the dispatcher later again
* to let draw unit try to start the rendering again.
*/
int32_t (*dispatch_cb)(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/**
*
* @param draw_unit
* @param task
* @return
*/
int32_t (*evaluate_cb)(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/**
* Called to signal the unit to complete all tasks in order to return their ready status.
* This callback can be implemented in case of asynchronous task processing.
* Below is an example to show the difference between synchronous and asynchronous:
*
* Synchronous:
* LVGL thread DRAW thread HW
*
* task1 --> submit --> Receive task1
* wait_for_finish()
* <-- task1->state = READY <-- Complete task1
* task2 --> submit --> Receive task2
* wait_for_finish()
* task2->state = READY <-- Complete task2
* task3 --> submit --> Receive task3
* wait_for_finish()
* <-- task3->state = READY <-- Complete task3
* task4 --> submit --> Receive task4
* wait_for_finish()
* <-- task4->state = READY <-- Complete task4
* NO MORE TASKS
*
*
* Asynchronous:
* LVGL thread DRAW thread HW
* is IDLE
* task1 --> queue task1
* submit --> Receive task1
* task2 --> queue task2 is BUSY (with task1)
* task3 --> queue task3 still BUSY (with task1)
* task4 --> queue task4 becomes IDLE
* <-- task1->state = READY <-- Complete task1
* submit --> Receive task2, task3, task4
* NO MORE TASKS
* wait_for_finish_cb() wait_for_finish()
* <-- Complete task2, task3, task4
* <-- task2->state = READY <--
* <-- task3->state = READY <--
* <-- task4->state = READY <--
*
* @param draw_unit
* @return
*/
int32_t (*wait_for_finish_cb)(lv_draw_unit_t * draw_unit);
/**
* Called to delete draw unit.
* @param draw_unit
* @return
*/
int32_t (*delete_cb)(lv_draw_unit_t * draw_unit);
};
typedef struct {
lv_draw_unit_t * unit_head;
uint32_t unit_cnt;
uint32_t used_memory_for_layers_kb;
#if LV_USE_OS
lv_thread_sync_t sync;
#else
int dispatch_req;
#endif
lv_mutex_t circle_cache_mutex;
bool task_running;
} lv_draw_global_info_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_PRIVATE_H*/

View File

@@ -1,302 +0,0 @@
/**
* @file lv_draw_rect.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_rect_private.h"
#include "lv_draw_private.h"
#include "../core/lv_obj.h"
#include "../misc/lv_assert.h"
#include "../core/lv_obj_event.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void LV_ATTRIBUTE_FAST_MEM lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(lv_draw_rect_dsc_t));
dsc->bg_color = lv_color_white();
dsc->bg_grad.stops[0].color = lv_color_white();
dsc->bg_grad.stops[1].color = lv_color_black();
dsc->bg_grad.stops[1].frac = 0xFF;
dsc->bg_grad.stops_count = 2;
dsc->border_color = lv_color_black();
dsc->shadow_color = lv_color_black();
dsc->bg_image_symbol_font = LV_FONT_DEFAULT;
dsc->bg_opa = LV_OPA_COVER;
dsc->bg_image_opa = LV_OPA_COVER;
dsc->outline_opa = LV_OPA_COVER;
dsc->border_opa = LV_OPA_COVER;
dsc->shadow_opa = LV_OPA_COVER;
dsc->border_side = LV_BORDER_SIDE_FULL;
}
void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t);
}
lv_draw_fill_dsc_t * lv_draw_task_get_fill_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_FILL ? (lv_draw_fill_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER;
dsc->side = LV_BORDER_SIDE_FULL;
dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
}
lv_draw_border_dsc_t * lv_draw_task_get_border_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_BORDER ? (lv_draw_border_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc)
{
lv_memzero(dsc, sizeof(*dsc));
dsc->opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t);
}
lv_draw_box_shadow_dsc_t * lv_draw_task_get_box_shadow_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_BOX_SHADOW ? (lv_draw_box_shadow_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
LV_PROFILER_BEGIN;
bool has_shadow;
bool has_fill;
bool has_border;
bool has_outline;
bool has_bg_img;
if(dsc->shadow_width == 0 ||
dsc->shadow_opa <= LV_OPA_MIN ||
(dsc->shadow_width == 1 && dsc->shadow_spread <= 0 &&
dsc->shadow_offset_x == 0 && dsc->shadow_offset_y == 0)) {
has_shadow = false;
}
else {
has_shadow = true;
}
if(dsc->bg_opa <= LV_OPA_MIN) has_fill = false;
else has_fill = true;
if(dsc->bg_image_opa <= LV_OPA_MIN || dsc->bg_image_src == NULL) has_bg_img = false;
else has_bg_img = true;
if(dsc->border_opa <= LV_OPA_MIN
|| dsc->border_width == 0
|| dsc->border_post == true
|| dsc->border_side == LV_BORDER_SIDE_NONE) has_border = false;
else has_border = true;
if(dsc->outline_opa <= LV_OPA_MIN || dsc->outline_width == 0) has_outline = false;
else has_outline = true;
bool bg_cover = true;
if(dsc->bg_opa < LV_OPA_COVER) bg_cover = false;
else if(dsc->bg_grad.dir != LV_GRAD_DIR_NONE) {
uint32_t s;
for(s = 0; s < dsc->bg_grad.stops_count; s++) {
if(dsc->bg_grad.stops[s].opa != LV_OPA_COVER) {
bg_cover = false;
break;
}
}
}
lv_draw_task_t * t;
/*Shadow*/
if(has_shadow) {
/*Check whether the shadow is visible*/
t = lv_draw_add_task(layer, coords);
lv_draw_box_shadow_dsc_t * shadow_dsc = lv_malloc(sizeof(lv_draw_box_shadow_dsc_t));
t->draw_dsc = shadow_dsc;
lv_area_increase(&t->_real_area, dsc->shadow_spread, dsc->shadow_spread);
lv_area_increase(&t->_real_area, dsc->shadow_width, dsc->shadow_width);
lv_area_move(&t->_real_area, dsc->shadow_offset_x, dsc->shadow_offset_y);
shadow_dsc->base = dsc->base;
shadow_dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t);
shadow_dsc->radius = dsc->radius;
shadow_dsc->color = dsc->shadow_color;
shadow_dsc->width = dsc->shadow_width;
shadow_dsc->spread = dsc->shadow_spread;
shadow_dsc->opa = dsc->shadow_opa;
shadow_dsc->ofs_x = dsc->shadow_offset_x;
shadow_dsc->ofs_y = dsc->shadow_offset_y;
shadow_dsc->bg_cover = bg_cover;
t->type = LV_DRAW_TASK_TYPE_BOX_SHADOW;
lv_draw_finalize_task_creation(layer, t);
}
/*Background*/
if(has_fill) {
lv_area_t bg_coords = *coords;
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) {
bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
}
t = lv_draw_add_task(layer, &bg_coords);
lv_draw_fill_dsc_t * bg_dsc = lv_malloc(sizeof(lv_draw_fill_dsc_t));
lv_draw_fill_dsc_init(bg_dsc);
t->draw_dsc = bg_dsc;
bg_dsc->base = dsc->base;
bg_dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t);
bg_dsc->radius = dsc->radius;
bg_dsc->color = dsc->bg_color;
bg_dsc->grad = dsc->bg_grad;
bg_dsc->opa = dsc->bg_opa;
t->type = LV_DRAW_TASK_TYPE_FILL;
lv_draw_finalize_task_creation(layer, t);
}
/*Background image*/
if(has_bg_img) {
lv_image_src_t src_type = lv_image_src_get_type(dsc->bg_image_src);
lv_result_t res = LV_RESULT_OK;
lv_image_header_t header;
if(src_type == LV_IMAGE_SRC_VARIABLE || src_type == LV_IMAGE_SRC_FILE) {
res = lv_image_decoder_get_info(dsc->bg_image_src, &header);
}
else if(src_type == LV_IMAGE_SRC_UNKNOWN) {
res = LV_RESULT_INVALID;
}
else {
lv_memzero(&header, sizeof(header));
}
if(res == LV_RESULT_OK) {
if(src_type == LV_IMAGE_SRC_VARIABLE || src_type == LV_IMAGE_SRC_FILE) {
if(dsc->bg_image_tiled) {
t = lv_draw_add_task(layer, coords);
}
else {
lv_area_t a = {0, 0, header.w - 1, header.h - 1};
lv_area_align(coords, &a, LV_ALIGN_CENTER, 0, 0);
t = lv_draw_add_task(layer, &a);
}
lv_draw_image_dsc_t * bg_image_dsc = lv_malloc(sizeof(lv_draw_image_dsc_t));
lv_draw_image_dsc_init(bg_image_dsc);
t->draw_dsc = bg_image_dsc;
bg_image_dsc->base = dsc->base;
bg_image_dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t);
bg_image_dsc->src = dsc->bg_image_src;
bg_image_dsc->opa = dsc->bg_image_opa;
bg_image_dsc->recolor = dsc->bg_image_recolor;
bg_image_dsc->recolor_opa = dsc->bg_image_recolor_opa;
bg_image_dsc->tile = dsc->bg_image_tiled;
bg_image_dsc->header = header;
bg_image_dsc->clip_radius = dsc->radius;
t->type = LV_DRAW_TASK_TYPE_IMAGE;
lv_draw_finalize_task_creation(layer, t);
}
else {
lv_point_t s;
lv_text_get_size(&s, dsc->bg_image_src, dsc->bg_image_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
lv_area_t a = {0, 0, s.x - 1, s.y - 1};
lv_area_align(coords, &a, LV_ALIGN_CENTER, 0, 0);
t = lv_draw_add_task(layer, &a);
lv_draw_label_dsc_t * bg_label_dsc = lv_malloc(sizeof(lv_draw_label_dsc_t));
lv_draw_label_dsc_init(bg_label_dsc);
t->draw_dsc = bg_label_dsc;
bg_label_dsc->base = dsc->base;
bg_label_dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t);
bg_label_dsc->color = dsc->bg_image_recolor;
bg_label_dsc->font = dsc->bg_image_symbol_font;
bg_label_dsc->text = dsc->bg_image_src;
t->type = LV_DRAW_TASK_TYPE_LABEL;
lv_draw_finalize_task_creation(layer, t);
}
}
}
/*Border*/
if(has_border) {
t = lv_draw_add_task(layer, coords);
lv_draw_border_dsc_t * border_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t));
t->draw_dsc = border_dsc;
border_dsc->base = dsc->base;
border_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
border_dsc->radius = dsc->radius;
border_dsc->color = dsc->border_color;
border_dsc->opa = dsc->border_opa;
border_dsc->width = dsc->border_width;
border_dsc->side = dsc->border_side;
t->type = LV_DRAW_TASK_TYPE_BORDER;
lv_draw_finalize_task_creation(layer, t);
}
/*Outline*/
if(has_outline) {
lv_area_t outline_coords = *coords;
lv_area_increase(&outline_coords, dsc->outline_width + dsc->outline_pad, dsc->outline_width + dsc->outline_pad);
t = lv_draw_add_task(layer, &outline_coords);
lv_draw_border_dsc_t * outline_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t));
t->draw_dsc = outline_dsc;
lv_area_increase(&t->_real_area, dsc->outline_width, dsc->outline_width);
lv_area_increase(&t->_real_area, dsc->outline_pad, dsc->outline_pad);
outline_dsc->base = dsc->base;
outline_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t);
outline_dsc->radius = dsc->radius == LV_RADIUS_CIRCLE ? LV_RADIUS_CIRCLE : dsc->radius + dsc->outline_width +
dsc->outline_pad;
outline_dsc->color = dsc->outline_color;
outline_dsc->opa = dsc->outline_opa;
outline_dsc->width = dsc->outline_width;
outline_dsc->side = LV_BORDER_SIDE_FULL;
t->type = LV_DRAW_TASK_TYPE_BORDER;
lv_draw_finalize_task_creation(layer, t);
}
LV_ASSERT_MEM_INTEGRITY();
LV_PROFILER_END;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,174 +0,0 @@
/**
* @file lv_draw_rect.h
*
*/
#ifndef LV_DRAW_RECT_H
#define LV_DRAW_RECT_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw.h"
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../misc/lv_style.h"
#include "sw/lv_draw_sw_gradient.h"
/*********************
* DEFINES
*********************/
#define LV_RADIUS_CIRCLE 0x7FFF /**< A very big radius to always draw as circle*/
LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE);
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
int32_t radius;
/*Background*/
lv_opa_t bg_opa;
lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/
lv_grad_dsc_t bg_grad;
/*Background img*/
const void * bg_image_src;
const void * bg_image_symbol_font;
lv_color_t bg_image_recolor;
lv_opa_t bg_image_opa;
lv_opa_t bg_image_recolor_opa;
uint8_t bg_image_tiled;
/*Border*/
lv_color_t border_color;
int32_t border_width;
lv_opa_t border_opa;
lv_border_side_t border_side : 5;
uint8_t border_post : 1; /*The border will be drawn later*/
/*Outline*/
lv_color_t outline_color;
int32_t outline_width;
int32_t outline_pad;
lv_opa_t outline_opa;
/*Shadow*/
lv_color_t shadow_color;
int32_t shadow_width;
int32_t shadow_offset_x;
int32_t shadow_offset_y;
int32_t shadow_spread;
lv_opa_t shadow_opa;
} lv_draw_rect_dsc_t;
typedef struct {
lv_draw_dsc_base_t base;
int32_t radius;
lv_opa_t opa;
lv_color_t color;
lv_grad_dsc_t grad;
} lv_draw_fill_dsc_t;
typedef struct {
lv_draw_dsc_base_t base;
int32_t radius;
lv_color_t color;
int32_t width;
lv_opa_t opa;
lv_border_side_t side : 5;
} lv_draw_border_dsc_t;
typedef struct {
lv_draw_dsc_base_t base;
int32_t radius;
lv_color_t color;
int32_t width;
int32_t spread;
int32_t ofs_x;
int32_t ofs_y;
lv_opa_t opa;
uint8_t bg_cover : 1;
} lv_draw_box_shadow_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a rectangle draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc);
/**
* Initialize a fill draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc);
/**
* Try to get a fill draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_FILL
*/
lv_draw_fill_dsc_t * lv_draw_task_get_fill_dsc(lv_draw_task_t * task);
/**
* Initialize a border draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc);
/**
* Try to get a border draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_BORDER
*/
lv_draw_border_dsc_t * lv_draw_task_get_border_dsc(lv_draw_task_t * task);
/**
* Initialize a box shadow draw descriptor.
* @param dsc pointer to a draw descriptor
*/
void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc);
/**
* Try to get a box shadow draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_BOX_SHADOW
*/
lv_draw_box_shadow_dsc_t * lv_draw_task_get_box_shadow_dsc(lv_draw_task_t * task);
/**
* The rectangle is a wrapper for fill, border, bg. image and box shadow.
* Internally fill, border, image and box shadow draw tasks will be created.
* @param layer pointer to a layer
* @param dsc pointer to an initialized draw descriptor variable
* @param coords the coordinates of the rectangle
*/
void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_RECT_H*/

View File

@@ -1,39 +0,0 @@
/**
* @file lv_draw_rect_private.h
*
*/
#ifndef LV_DRAW_RECT_PRIVATE_H
#define LV_DRAW_RECT_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_RECT_PRIVATE_H*/

View File

@@ -1,83 +0,0 @@
/**
* @file lv_draw_triangle.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_triangle_private.h"
#include "lv_draw_private.h"
#include "../core/lv_obj.h"
#include "../misc/lv_math.h"
#include "../stdlib/lv_mem.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_triangle_dsc_init(lv_draw_triangle_dsc_t * dsc)
{
LV_PROFILER_BEGIN;
lv_memzero(dsc, sizeof(lv_draw_triangle_dsc_t));
dsc->bg_color = lv_color_white();
dsc->bg_grad.stops[0].color = lv_color_white();
dsc->bg_grad.stops[1].color = lv_color_black();
dsc->bg_grad.stops[1].frac = 0xFF;
dsc->bg_grad.stops_count = 2;
dsc->bg_opa = LV_OPA_COVER;
dsc->base.dsc_size = sizeof(lv_draw_triangle_dsc_t);
LV_PROFILER_END;
}
lv_draw_triangle_dsc_t * lv_draw_task_get_triangle_dsc(lv_draw_task_t * task)
{
return task->type == LV_DRAW_TASK_TYPE_TRIANGLE ? (lv_draw_triangle_dsc_t *)task->draw_dsc : NULL;
}
void lv_draw_triangle(lv_layer_t * layer, const lv_draw_triangle_dsc_t * dsc)
{
if(dsc->bg_opa <= LV_OPA_MIN) return;
LV_PROFILER_BEGIN;
lv_area_t a;
a.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
a.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
a.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
a.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
lv_draw_task_t * t = lv_draw_add_task(layer, &a);
t->draw_dsc = lv_malloc(sizeof(*dsc));
lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc));
t->type = LV_DRAW_TASK_TYPE_TRIANGLE;
lv_draw_finalize_task_creation(layer, t);
LV_PROFILER_END;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,67 +0,0 @@
/**
* @file lv_draw_triangle.h
*
*/
#ifndef LV_DRAW_TRIANGLE_H
#define LV_DRAW_TRIANGLE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_dsc_base_t base;
lv_opa_t bg_opa;
lv_color_t bg_color;
lv_grad_dsc_t bg_grad;
lv_point_precise_t p[3];
} lv_draw_triangle_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize a triangle draw descriptor
* @param draw_dsc pointer to a draw descriptor
*/
void lv_draw_triangle_dsc_init(lv_draw_triangle_dsc_t * draw_dsc);
/**
* Try to get a triangle draw descriptor from a draw task.
* @param task draw task
* @return the task's draw descriptor or NULL if the task is not of type LV_DRAW_TASK_TYPE_TRIANGLE
*/
lv_draw_triangle_dsc_t * lv_draw_task_get_triangle_dsc(lv_draw_task_t * task);
/**
* Create a triangle draw task
* @param layer pointer to a layer
* @param draw_dsc pointer to an initialized `lv_draw_triangle_dsc_t` object
*/
void lv_draw_triangle(lv_layer_t * layer, const lv_draw_triangle_dsc_t * draw_dsc);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_TRIANGLE_H*/

View File

@@ -1,43 +0,0 @@
/**
* @file lv_draw_triangle_private.h
*
*/
#ifndef LV_DRAW_TRIANGLE_PRIVATE_H
#define LV_DRAW_TRIANGLE_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_triangle.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_TRIANGLE_PRIVATE_H*/

View File

@@ -1,804 +0,0 @@
/**
* @file lv_draw_vector.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vector_private.h"
#include "../misc/lv_area_private.h"
#include "lv_draw_private.h"
#if LV_USE_VECTOR_GRAPHIC
#include "../misc/lv_ll.h"
#include "../misc/lv_types.h"
#include "../stdlib/lv_string.h"
#include <math.h>
#include <float.h>
#define MATH_PI 3.14159265358979323846f
#define MATH_HALF_PI 1.57079632679489661923f
#define DEG_TO_RAD 0.017453292519943295769236907684886f
#define RAD_TO_DEG 57.295779513082320876798154814105f
#define MATH_RADIANS(deg) ((deg) * DEG_TO_RAD)
#define MATH_DEGREES(rad) ((rad) * RAD_TO_DEG)
/*********************
* DEFINES
*********************/
#ifndef M_PI
#define M_PI 3.1415926f
#endif
#define CHECK_AND_RESIZE_PATH_CONTAINER(P, N) \
do { \
if ((lv_array_size(&(P)->ops) + (N)) > lv_array_capacity(&(P)->ops)) { \
lv_array_resize(&(P)->ops, ((P)->ops.capacity << 1)); \
} \
if ((lv_array_size(&(P)->points) + (N)) > lv_array_capacity(&(P)->points)) { \
lv_array_resize(&(P)->points, ((P)->points.capacity << 1)); \
} \
} while(0)
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_vector_path_t * path;
lv_vector_draw_dsc_t dsc;
} lv_vector_draw_task;
/**********************
* STATIC PROTOTYPES
**********************/
static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_t * src)
{
lv_memcpy(&(dst->fill_dsc), &(src->fill_dsc), sizeof(lv_vector_fill_dsc_t));
dst->stroke_dsc.style = src->stroke_dsc.style;
dst->stroke_dsc.color = src->stroke_dsc.color;
dst->stroke_dsc.opa = src->stroke_dsc.opa;
dst->stroke_dsc.width = src->stroke_dsc.width;
dst->stroke_dsc.cap = src->stroke_dsc.cap;
dst->stroke_dsc.join = src->stroke_dsc.join;
dst->stroke_dsc.miter_limit = src->stroke_dsc.miter_limit;
lv_array_copy(&(dst->stroke_dsc.dash_pattern), &(src->stroke_dsc.dash_pattern));
dst->stroke_dsc.gradient.style = src->stroke_dsc.gradient.style;
dst->stroke_dsc.gradient.cx = src->stroke_dsc.gradient.cx;
dst->stroke_dsc.gradient.cy = src->stroke_dsc.gradient.cy;
dst->stroke_dsc.gradient.cr = src->stroke_dsc.gradient.cr;
dst->stroke_dsc.gradient.spread = src->fill_dsc.gradient.spread;
lv_memcpy(&(dst->stroke_dsc.gradient), &(src->stroke_dsc.gradient), sizeof(lv_vector_gradient_t));
lv_memcpy(&(dst->stroke_dsc.matrix), &(src->stroke_dsc.matrix), sizeof(lv_matrix_t));
dst->blend_mode = src->blend_mode;
lv_memcpy(&(dst->matrix), &(src->matrix), sizeof(lv_matrix_t));
lv_area_copy(&(dst->scissor_area), &(src->scissor_area));
}
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_matrix_transform_point(const lv_matrix_t * matrix, lv_fpoint_t * point)
{
float x = point->x;
float y = point->y;
point->x = x * matrix->m[0][0] + y * matrix->m[1][0] + matrix->m[0][2];
point->y = x * matrix->m[0][1] + y * matrix->m[1][1] + matrix->m[1][2];
}
void lv_matrix_transform_path(const lv_matrix_t * matrix, lv_vector_path_t * path)
{
lv_fpoint_t * pt = lv_array_front(&path->points);
uint32_t size = lv_array_size(&path->points);
for(uint32_t i = 0; i < size; i++) {
lv_matrix_transform_point(matrix, &pt[i]);
}
}
/* path functions */
lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality)
{
lv_vector_path_t * path = lv_malloc(sizeof(lv_vector_path_t));
LV_ASSERT_MALLOC(path);
lv_memzero(path, sizeof(lv_vector_path_t));
path->quality = quality;
lv_array_init(&path->ops, 8, sizeof(lv_vector_path_op_t));
lv_array_init(&path->points, 8, sizeof(lv_fpoint_t));
return path;
}
void lv_vector_path_copy(lv_vector_path_t * target_path, const lv_vector_path_t * path)
{
target_path->quality = path->quality;
lv_array_copy(&target_path->ops, &path->ops);
lv_array_copy(&target_path->points, &path->points);
}
void lv_vector_path_clear(lv_vector_path_t * path)
{
lv_array_clear(&path->ops);
lv_array_clear(&path->points);
}
void lv_vector_path_delete(lv_vector_path_t * path)
{
lv_array_deinit(&path->ops);
lv_array_deinit(&path->points);
lv_free(path);
}
void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p)
{
CHECK_AND_RESIZE_PATH_CONTAINER(path, 1);
lv_vector_path_op_t op = LV_VECTOR_PATH_OP_MOVE_TO;
lv_array_push_back(&path->ops, &op);
lv_array_push_back(&path->points, p);
}
void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p)
{
if(lv_array_is_empty(&path->ops)) {
/*first op must be move_to*/
return;
}
CHECK_AND_RESIZE_PATH_CONTAINER(path, 1);
lv_vector_path_op_t op = LV_VECTOR_PATH_OP_LINE_TO;
lv_array_push_back(&path->ops, &op);
lv_array_push_back(&path->points, p);
}
void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2)
{
if(lv_array_is_empty(&path->ops)) {
/*first op must be move_to*/
return;
}
CHECK_AND_RESIZE_PATH_CONTAINER(path, 2);
lv_vector_path_op_t op = LV_VECTOR_PATH_OP_QUAD_TO;
lv_array_push_back(&path->ops, &op);
lv_array_push_back(&path->points, p1);
lv_array_push_back(&path->points, p2);
}
void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2,
const lv_fpoint_t * p3)
{
if(lv_array_is_empty(&path->ops)) {
/*first op must be move_to*/
return;
}
CHECK_AND_RESIZE_PATH_CONTAINER(path, 3);
lv_vector_path_op_t op = LV_VECTOR_PATH_OP_CUBIC_TO;
lv_array_push_back(&path->ops, &op);
lv_array_push_back(&path->points, p1);
lv_array_push_back(&path->points, p2);
lv_array_push_back(&path->points, p3);
}
void lv_vector_path_close(lv_vector_path_t * path)
{
if(lv_array_is_empty(&path->ops)) {
/*first op must be move_to*/
return;
}
CHECK_AND_RESIZE_PATH_CONTAINER(path, 1);
lv_vector_path_op_t op = LV_VECTOR_PATH_OP_CLOSE;
lv_array_push_back(&path->ops, &op);
}
void lv_vector_path_get_bounding(const lv_vector_path_t * path, lv_area_t * area)
{
LV_ASSERT_NULL(path);
LV_ASSERT_NULL(area);
uint32_t len = lv_array_size(&path->points);
if(len == 0) {
lv_memzero(area, sizeof(lv_area_t));
return;
}
lv_fpoint_t * p = lv_array_front(&path->points);
float x1 = p[0].x;
float x2 = p[0].x;
float y1 = p[0].y;
float y2 = p[0].y;
for(uint32_t i = 1; i < len; i++) {
if(p[i].x < x1) x1 = p[i].x;
if(p[i].y < y1) y1 = p[i].y;
if(p[i].x > x2) x2 = p[i].x;
if(p[i].y > y2) y2 = p[i].y;
}
area->x1 = (int32_t)x1;
area->y1 = (int32_t)y1;
area->x2 = (int32_t)x2;
area->y2 = (int32_t)y2;
}
void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry)
{
float x = rect->x1;
float y = rect->y1;
float w = (float)lv_area_get_width(rect);
float h = (float)lv_area_get_height(rect);
float hw = w * 0.5f;
float hh = h * 0.5f;
if(rx > hw) rx = hw;
if(ry > hh) ry = hh;
if(rx == 0 && ry == 0) {
lv_fpoint_t pt = {x, y};
lv_vector_path_move_to(path, &pt);
pt.x += w;
lv_vector_path_line_to(path, &pt);
pt.y += h;
lv_vector_path_line_to(path, &pt);
pt.x -= w;
lv_vector_path_line_to(path, &pt);
lv_vector_path_close(path);
}
else if(rx == hw && ry == hh) {
lv_fpoint_t pt = {x + w * 0.5f, y + h * 0.5f};
lv_vector_path_append_circle(path, &pt, rx, ry);
}
else {
float hrx = rx * 0.5f;
float hry = ry * 0.5f;
lv_fpoint_t pt, pt2, pt3;
pt.x = x + rx;
pt.y = y;
lv_vector_path_move_to(path, &pt);
pt.x = x + w - rx;
pt.y = y;
lv_vector_path_line_to(path, &pt);
pt.x = x + w - rx + hrx;
pt.y = y;
pt2.x = x + w;
pt2.y = y + ry - hry;
pt3.x = x + w;
pt3.y = y + ry;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = x + w;
pt.y = y + h - ry;
lv_vector_path_line_to(path, &pt);
pt.x = x + w;
pt.y = y + h - ry + hry;
pt2.x = x + w - rx + hrx;
pt2.y = y + h;
pt3.x = x + w - rx;
pt3.y = y + h;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = x + rx;
pt.y = y + h;
lv_vector_path_line_to(path, &pt);
pt.x = x + rx - hrx;
pt.y = y + h;
pt2.x = x;
pt2.y = y + h - ry + hry;
pt3.x = x;
pt3.y = y + h - ry;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = x;
pt.y = y + ry;
lv_vector_path_line_to(path, &pt);
pt.x = x;
pt.y = y + ry - hry;
pt2.x = x + rx - hrx;
pt2.y = y;
pt3.x = x + rx;
pt3.y = y;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
lv_vector_path_close(path);
}
}
void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry)
{
float krx = rx * 0.552284f;
float kry = ry * 0.552284f;
float cx = c->x;
float cy = c->y;
lv_fpoint_t pt, pt2, pt3;
pt.x = cx;
pt.y = cy - ry;
lv_vector_path_move_to(path, &pt);
pt.x = cx + krx;
pt.y = cy - ry;
pt2.x = cx + rx;
pt2.y = cy - kry;
pt3.x = cx + rx;
pt3.y = cy;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = cx + rx;
pt.y = cy + kry;
pt2.x = cx + krx;
pt2.y = cy + ry;
pt3.x = cx;
pt3.y = cy + ry;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = cx - krx;
pt.y = cy + ry;
pt2.x = cx - rx;
pt2.y = cy + kry;
pt3.x = cx - rx;
pt3.y = cy;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
pt.x = cx - rx;
pt.y = cy - kry;
pt2.x = cx - krx;
pt2.y = cy - ry;
pt3.x = cx;
pt3.y = cy - ry;
lv_vector_path_cubic_to(path, &pt, &pt2, &pt3);
lv_vector_path_close(path);
}
/**
* Add a arc to the path
* @param path pointer to a path
* @param c pointer to a `lv_fpoint_t` variable for center of the circle
* @param radius the radius for arc
* @param start_angle the start angle for arc
* @param sweep the sweep angle for arc, could be negative
* @param pie true: draw a pie, false: draw a arc
*/
void lv_vector_path_append_arc(lv_vector_path_t * path, const lv_fpoint_t * c, float radius, float start_angle,
float sweep, bool pie)
{
float cx = c->x;
float cy = c->y;
/* just circle */
if(sweep >= 360.0f || sweep <= -360.0f) {
lv_vector_path_append_circle(path, c, radius, radius);
return;
}
start_angle = MATH_RADIANS(start_angle);
sweep = MATH_RADIANS(sweep);
int n_curves = (int)ceil(fabsf(sweep / MATH_HALF_PI));
float sweep_sign = sweep < 0 ? -1.f : 1.f;
float fract = fmodf(sweep, MATH_HALF_PI);
fract = (fabsf(fract) < FLT_EPSILON) ? MATH_HALF_PI * sweep_sign : fract;
/* Start from here */
lv_fpoint_t start = {
.x = radius * cosf(start_angle),
.y = radius * sinf(start_angle),
};
if(pie) {
lv_vector_path_move_to(path, &(lv_fpoint_t) {
cx, cy
});
lv_vector_path_line_to(path, &(lv_fpoint_t) {
start.x + cx, start.y + cy
});
}
for(int i = 0; i < n_curves; ++i) {
float end_angle = start_angle + ((i != n_curves - 1) ? MATH_HALF_PI * sweep_sign : fract);
float end_x = radius * cosf(end_angle);
float end_y = radius * sinf(end_angle);
/* variables needed to calculate bezier control points */
/** get bezier control points using article:
* (http://itc.ktu.lt/index.php/ITC/article/view/11812/6479)
*/
float ax = start.x;
float ay = start.y;
float bx = end_x;
float by = end_y;
float q1 = ax * ax + ay * ay;
float q2 = ax * bx + ay * by + q1;
float k2 = (4.0f / 3.0f) * ((sqrtf(2 * q1 * q2) - q2) / (ax * by - ay * bx));
/* Next start point is the current end point */
start.x = end_x;
start.y = end_y;
end_x += cx;
end_y += cy;
lv_fpoint_t ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy};
lv_fpoint_t ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy};
lv_fpoint_t end = {end_x, end_y};
lv_vector_path_cubic_to(path, &ctrl1, &ctrl2, &end);
start_angle = end_angle;
}
if(pie) {
lv_vector_path_close(path);
}
}
void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath)
{
uint32_t ops_size = lv_array_size(&path->ops);
uint32_t nops_size = lv_array_size(&subpath->ops);
uint32_t point_size = lv_array_size(&path->points);
uint32_t npoint_size = lv_array_size(&subpath->points);
lv_array_concat(&path->ops, &subpath->ops);
path->ops.size = ops_size + nops_size;
lv_array_concat(&path->points, &subpath->points);
path->points.size = point_size + npoint_size;
}
/* draw dsc functions */
lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer)
{
lv_vector_dsc_t * dsc = lv_malloc(sizeof(lv_vector_dsc_t));
LV_ASSERT_MALLOC(dsc);
lv_memzero(dsc, sizeof(lv_vector_dsc_t));
dsc->layer = layer;
lv_vector_fill_dsc_t * fill_dsc = &(dsc->current_dsc.fill_dsc);
fill_dsc->style = LV_VECTOR_DRAW_STYLE_SOLID;
fill_dsc->color = lv_color_to_32(lv_color_black(), 0xFF);
fill_dsc->opa = LV_OPA_COVER;
fill_dsc->fill_rule = LV_VECTOR_FILL_NONZERO;
lv_matrix_identity(&(fill_dsc->matrix)); /*identity matrix*/
lv_vector_stroke_dsc_t * stroke_dsc = &(dsc->current_dsc.stroke_dsc);
stroke_dsc->style = LV_VECTOR_DRAW_STYLE_SOLID;
stroke_dsc->color = lv_color_to_32(lv_color_black(), 0xFF);
stroke_dsc->opa = LV_OPA_0; /*default no stroke*/
stroke_dsc->width = 1.0f;
stroke_dsc->cap = LV_VECTOR_STROKE_CAP_BUTT;
stroke_dsc->join = LV_VECTOR_STROKE_JOIN_MITER;
stroke_dsc->miter_limit = 4.0f;
lv_matrix_identity(&(stroke_dsc->matrix)); /*identity matrix*/
dsc->current_dsc.blend_mode = LV_VECTOR_BLEND_SRC_OVER;
dsc->current_dsc.scissor_area = layer->_clip_area;
lv_matrix_identity(&(dsc->current_dsc.matrix)); /*identity matrix*/
dsc->tasks.task_list = NULL;
return dsc;
}
void lv_vector_dsc_delete(lv_vector_dsc_t * dsc)
{
if(dsc->tasks.task_list) {
lv_ll_t * task_list = dsc->tasks.task_list;
lv_vector_for_each_destroy_tasks(task_list, NULL, NULL);
dsc->tasks.task_list = NULL;
}
lv_array_deinit(&(dsc->current_dsc.stroke_dsc.dash_pattern));
lv_free(dsc);
}
void lv_vector_dsc_set_blend_mode(lv_vector_dsc_t * dsc, lv_vector_blend_t blend)
{
dsc->current_dsc.blend_mode = blend;
}
void lv_vector_dsc_set_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix)
{
lv_memcpy(&(dsc->current_dsc.matrix), matrix, sizeof(lv_matrix_t));
}
void lv_vector_dsc_set_fill_color(lv_vector_dsc_t * dsc, lv_color_t color)
{
dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID;
dsc->current_dsc.fill_dsc.color = lv_color_to_32(color, 0xFF);
}
void lv_vector_dsc_set_fill_color32(lv_vector_dsc_t * dsc, lv_color32_t color)
{
dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID;
dsc->current_dsc.fill_dsc.color = color;
}
void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa)
{
dsc->current_dsc.fill_dsc.opa = opa;
}
void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule)
{
dsc->current_dsc.fill_dsc.fill_rule = rule;
}
void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc)
{
dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_PATTERN;
lv_memcpy(&(dsc->current_dsc.fill_dsc.img_dsc), img_dsc, sizeof(lv_draw_image_dsc_t));
}
void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2)
{
dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT;
dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR;
dsc->current_dsc.fill_dsc.gradient.x1 = x1;
dsc->current_dsc.fill_dsc.gradient.y1 = y1;
dsc->current_dsc.fill_dsc.gradient.x2 = x2;
dsc->current_dsc.fill_dsc.gradient.y2 = y2;
}
void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius)
{
dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT;
dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL;
dsc->current_dsc.fill_dsc.gradient.cx = cx;
dsc->current_dsc.fill_dsc.gradient.cy = cy;
dsc->current_dsc.fill_dsc.gradient.cr = radius;
}
void lv_vector_dsc_set_fill_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread)
{
dsc->current_dsc.fill_dsc.gradient.spread = spread;
}
void lv_vector_dsc_set_fill_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops,
uint16_t count)
{
if(count > LV_GRADIENT_MAX_STOPS) {
LV_LOG_WARN("Gradient stops limited: %d, max: %d", count, LV_GRADIENT_MAX_STOPS);
count = LV_GRADIENT_MAX_STOPS;
}
lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.stops), stops, sizeof(lv_gradient_stop_t) * count);
dsc->current_dsc.fill_dsc.gradient.stops_count = count;
}
void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix)
{
lv_memcpy(&(dsc->current_dsc.fill_dsc.matrix), matrix, sizeof(lv_matrix_t));
}
void lv_vector_dsc_set_stroke_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix)
{
lv_memcpy(&(dsc->current_dsc.stroke_dsc.matrix), matrix, sizeof(lv_matrix_t));
}
void lv_vector_dsc_set_stroke_color32(lv_vector_dsc_t * dsc, lv_color32_t color)
{
dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID;
dsc->current_dsc.stroke_dsc.color = color;
}
void lv_vector_dsc_set_stroke_color(lv_vector_dsc_t * dsc, lv_color_t color)
{
dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID;
dsc->current_dsc.stroke_dsc.color = lv_color_to_32(color, 0xFF);
}
void lv_vector_dsc_set_stroke_opa(lv_vector_dsc_t * dsc, lv_opa_t opa)
{
dsc->current_dsc.stroke_dsc.opa = opa;
}
void lv_vector_dsc_set_stroke_width(lv_vector_dsc_t * dsc, float width)
{
dsc->current_dsc.stroke_dsc.width = width;
}
void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, uint16_t dash_count)
{
lv_array_t * dash_array = &(dsc->current_dsc.stroke_dsc.dash_pattern);
if(dash_pattern) {
lv_array_clear(dash_array);
if(lv_array_capacity(dash_array) == 0) {
lv_array_init(dash_array, dash_count, sizeof(float));
}
else {
lv_array_resize(dash_array, dash_count);
}
for(uint16_t i = 0; i < dash_count; i++) {
lv_array_push_back(dash_array, &dash_pattern[i]);
}
}
else { /*clear dash*/
lv_array_clear(dash_array);
}
}
void lv_vector_dsc_set_stroke_cap(lv_vector_dsc_t * dsc, lv_vector_stroke_cap_t cap)
{
dsc->current_dsc.stroke_dsc.cap = cap;
}
void lv_vector_dsc_set_stroke_join(lv_vector_dsc_t * dsc, lv_vector_stroke_join_t join)
{
dsc->current_dsc.stroke_dsc.join = join;
}
void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_limit)
{
dsc->current_dsc.stroke_dsc.miter_limit = miter_limit;
}
void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2)
{
dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT;
dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR;
dsc->current_dsc.stroke_dsc.gradient.x1 = x1;
dsc->current_dsc.stroke_dsc.gradient.y1 = y1;
dsc->current_dsc.stroke_dsc.gradient.x2 = x2;
dsc->current_dsc.stroke_dsc.gradient.y2 = y2;
}
void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius)
{
dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT;
dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL;
dsc->current_dsc.stroke_dsc.gradient.cx = cx;
dsc->current_dsc.stroke_dsc.gradient.cy = cy;
dsc->current_dsc.stroke_dsc.gradient.cr = radius;
}
void lv_vector_dsc_set_stroke_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread)
{
dsc->current_dsc.stroke_dsc.gradient.spread = spread;
}
void lv_vector_dsc_set_stroke_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops,
uint16_t count)
{
if(count > LV_GRADIENT_MAX_STOPS) {
LV_LOG_WARN("Gradient stops limited: %d, max: %d", count, LV_GRADIENT_MAX_STOPS);
count = LV_GRADIENT_MAX_STOPS;
}
lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.stops), stops, sizeof(lv_gradient_stop_t) * count);
dsc->current_dsc.stroke_dsc.gradient.stops_count = count;
}
/* draw functions */
void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path)
{
lv_area_t rect;
if(!lv_area_intersect(&rect, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) {
return;
}
if(dsc->current_dsc.fill_dsc.opa == 0
&& dsc->current_dsc.stroke_dsc.opa == 0) {
return;
}
if(!dsc->tasks.task_list) {
dsc->tasks.task_list = lv_malloc(sizeof(lv_ll_t));
LV_ASSERT_MALLOC(dsc->tasks.task_list);
lv_ll_init(dsc->tasks.task_list, sizeof(lv_vector_draw_task));
}
lv_vector_draw_task * new_task = (lv_vector_draw_task *)lv_ll_ins_tail(dsc->tasks.task_list);
lv_memset(new_task, 0, sizeof(lv_vector_draw_task));
new_task->path = lv_vector_path_create(0);
_copy_draw_dsc(&(new_task->dsc), &(dsc->current_dsc));
lv_vector_path_copy(new_task->path, path);
new_task->dsc.scissor_area = rect;
}
void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect)
{
lv_area_t r;
if(!lv_area_intersect(&r, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) {
return;
}
if(!dsc->tasks.task_list) {
dsc->tasks.task_list = lv_malloc(sizeof(lv_ll_t));
LV_ASSERT_MALLOC(dsc->tasks.task_list);
lv_ll_init(dsc->tasks.task_list, sizeof(lv_vector_draw_task));
}
lv_vector_draw_task * new_task = (lv_vector_draw_task *)lv_ll_ins_tail(dsc->tasks.task_list);
lv_memset(new_task, 0, sizeof(lv_vector_draw_task));
new_task->dsc.fill_dsc.color = dsc->current_dsc.fill_dsc.color;
new_task->dsc.fill_dsc.opa = dsc->current_dsc.fill_dsc.opa;
lv_area_copy(&(new_task->dsc.scissor_area), rect);
}
void lv_draw_vector(lv_vector_dsc_t * dsc)
{
if(!dsc->tasks.task_list) {
return;
}
lv_layer_t * layer = dsc->layer;
lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->_clip_area));
t->type = LV_DRAW_TASK_TYPE_VECTOR;
t->draw_dsc = lv_malloc(sizeof(lv_draw_vector_task_dsc_t));
lv_memcpy(t->draw_dsc, &(dsc->tasks), sizeof(lv_draw_vector_task_dsc_t));
lv_draw_finalize_task_creation(layer, t);
dsc->tasks.task_list = NULL;
}
/* draw dsc transform */
void lv_vector_dsc_identity(lv_vector_dsc_t * dsc)
{
lv_matrix_identity(&(dsc->current_dsc.matrix)); /*identity matrix*/
}
void lv_vector_dsc_scale(lv_vector_dsc_t * dsc, float scale_x, float scale_y)
{
lv_matrix_scale(&(dsc->current_dsc.matrix), scale_x, scale_y);
}
void lv_vector_dsc_rotate(lv_vector_dsc_t * dsc, float degree)
{
lv_matrix_rotate(&(dsc->current_dsc.matrix), degree);
}
void lv_vector_dsc_translate(lv_vector_dsc_t * dsc, float tx, float ty)
{
lv_matrix_translate(&(dsc->current_dsc.matrix), tx, ty);
}
void lv_vector_dsc_skew(lv_vector_dsc_t * dsc, float skew_x, float skew_y)
{
lv_matrix_skew(&(dsc->current_dsc.matrix), skew_x, skew_y);
}
void lv_vector_for_each_destroy_tasks(lv_ll_t * task_list, vector_draw_task_cb cb, void * data)
{
lv_vector_draw_task * task = lv_ll_get_head(task_list);
lv_vector_draw_task * next_task = NULL;
while(task != NULL) {
next_task = lv_ll_get_next(task_list, task);
lv_ll_remove(task_list, task);
if(cb) {
cb(data, task->path, &(task->dsc));
}
if(task->path) {
lv_vector_path_delete(task->path);
}
lv_array_deinit(&(task->dsc.stroke_dsc.dash_pattern));
lv_free(task);
task = next_task;
}
lv_free(task_list);
}
#endif /* LV_USE_VECTOR_GRAPHIC */

View File

@@ -1,489 +0,0 @@
/**
* @file lv_draw_vector.h
*
*/
#ifndef LV_DRAW_VECTOR_H
#define LV_DRAW_VECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../misc/lv_array.h"
#include "../misc/lv_matrix.h"
#include "lv_draw_image.h"
#if LV_USE_VECTOR_GRAPHIC
#if !LV_USE_MATRIX
#error "lv_draw_vector needs LV_USE_MATRIX = 1"
#endif
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_VECTOR_FILL_NONZERO = 0,
LV_VECTOR_FILL_EVENODD,
} lv_vector_fill_t;
typedef enum {
LV_VECTOR_STROKE_CAP_BUTT = 0,
LV_VECTOR_STROKE_CAP_SQUARE,
LV_VECTOR_STROKE_CAP_ROUND,
} lv_vector_stroke_cap_t;
typedef enum {
LV_VECTOR_STROKE_JOIN_MITER = 0,
LV_VECTOR_STROKE_JOIN_BEVEL,
LV_VECTOR_STROKE_JOIN_ROUND,
} lv_vector_stroke_join_t;
typedef enum {
LV_VECTOR_PATH_QUALITY_MEDIUM = 0, /* default*/
LV_VECTOR_PATH_QUALITY_HIGH,
LV_VECTOR_PATH_QUALITY_LOW,
} lv_vector_path_quality_t;
typedef enum {
LV_VECTOR_BLEND_SRC_OVER = 0,
LV_VECTOR_BLEND_SRC_IN,
LV_VECTOR_BLEND_DST_OVER,
LV_VECTOR_BLEND_DST_IN,
LV_VECTOR_BLEND_SCREEN,
LV_VECTOR_BLEND_MULTIPLY,
LV_VECTOR_BLEND_NONE,
LV_VECTOR_BLEND_ADDITIVE,
LV_VECTOR_BLEND_SUBTRACTIVE,
} lv_vector_blend_t;
typedef enum {
LV_VECTOR_PATH_OP_MOVE_TO = 0,
LV_VECTOR_PATH_OP_LINE_TO,
LV_VECTOR_PATH_OP_QUAD_TO,
LV_VECTOR_PATH_OP_CUBIC_TO,
LV_VECTOR_PATH_OP_CLOSE,
} lv_vector_path_op_t;
typedef enum {
LV_VECTOR_DRAW_STYLE_SOLID = 0,
LV_VECTOR_DRAW_STYLE_PATTERN,
LV_VECTOR_DRAW_STYLE_GRADIENT,
} lv_vector_draw_style_t;
typedef enum {
LV_VECTOR_GRADIENT_SPREAD_PAD = 0,
LV_VECTOR_GRADIENT_SPREAD_REPEAT,
LV_VECTOR_GRADIENT_SPREAD_REFLECT,
} lv_vector_gradient_spread_t;
typedef enum {
LV_VECTOR_GRADIENT_STYLE_LINEAR = 0,
LV_VECTOR_GRADIENT_STYLE_RADIAL,
} lv_vector_gradient_style_t;
struct lv_fpoint_t {
float x;
float y;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Transform the coordinates of a point using given matrix
* @param matrix pointer to a matrix
* @param point pointer to a point
*/
void lv_matrix_transform_point(const lv_matrix_t * matrix, lv_fpoint_t * point);
/**
* Transform all the coordinates of a path using given matrix
* @param matrix pointer to a matrix
* @param path pointer to a path
*/
void lv_matrix_transform_path(const lv_matrix_t * matrix, lv_vector_path_t * path);
/**
* Create a vector graphic path object
* @param quality the quality hint of path
* @return pointer to the created path object
*/
lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality);
/**
* Copy a path data to another
* @param target_path pointer to a path
* @param path pointer to source path
*/
void lv_vector_path_copy(lv_vector_path_t * target_path, const lv_vector_path_t * path);
/**
* Clear path data
* @param path pointer to a path
*/
void lv_vector_path_clear(lv_vector_path_t * path);
/**
* Delete the graphic path object
* @param path pointer to a path
*/
void lv_vector_path_delete(lv_vector_path_t * path);
/**
* Begin a new sub path and set a point to path
* @param path pointer to a path
* @param p pointer to a `lv_fpoint_t` variable
*/
void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p);
/**
* Add a line to the path from last point to the point
* @param path pointer to a path
* @param p pointer to a `lv_fpoint_t` variable
*/
void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p);
/**
* Add a quadratic bezier line to the path from last point to the point
* @param path pointer to a path
* @param p1 pointer to a `lv_fpoint_t` variable for control point
* @param p2 pointer to a `lv_fpoint_t` variable for end point
*/
void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2);
/**
* Add a cubic bezier line to the path from last point to the point
* @param path pointer to a path
* @param p1 pointer to a `lv_fpoint_t` variable for first control point
* @param p2 pointer to a `lv_fpoint_t` variable for second control point
* @param p3 pointer to a `lv_fpoint_t` variable for end point
*/
void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2,
const lv_fpoint_t * p3);
/**
* Close the sub path
* @param path pointer to a path
*/
void lv_vector_path_close(lv_vector_path_t * path);
/**
* Get the bounding box of a path
* @param path pointer to a path
* @param area pointer to a `lv_area_t` variable for bounding box
*/
void lv_vector_path_get_bounding(const lv_vector_path_t * path, lv_area_t * area);
/**
* Add a rectangle to the path
* @param path pointer to a path
* @param rect pointer to a `lv_area_t` variable
* @param rx the horizontal radius for rounded rectangle
* @param ry the vertical radius for rounded rectangle
*/
void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry);
/**
* Add a circle to the path
* @param path pointer to a path
* @param c pointer to a `lv_fpoint_t` variable for center of the circle
* @param rx the horizontal radius for circle
* @param ry the vertical radius for circle
*/
void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry);
/**
* Add a arc to the path
* @param path pointer to a path
* @param c pointer to a `lv_fpoint_t` variable for center of the circle
* @param radius the radius for arc
* @param start_angle the start angle for arc
* @param sweep the sweep angle for arc, could be negative
* @param pie true: draw a pie, false: draw a arc
*/
void lv_vector_path_append_arc(lv_vector_path_t * path, const lv_fpoint_t * c, float radius, float start_angle,
float sweep, bool pie);
/**
* Add an sub path to the path
* @param path pointer to a path
* @param subpath pointer to another path which will be added
*/
void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath);
/**
* Create a vector graphic descriptor
* @param layer pointer to a layer
* @return pointer to the created descriptor
*/
lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer);
/**
* Delete the vector graphic descriptor
* @param dsc pointer to a vector graphic descriptor
*/
void lv_vector_dsc_delete(lv_vector_dsc_t * dsc);
/**
* Set a matrix to current transformation matrix
* @param dsc pointer to a vector graphic descriptor
* @param matrix pointer to a matrix
*/
void lv_vector_dsc_set_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix);
/**
* Set blend mode for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param blend the blend mode to be set in `lv_vector_blend_t`
*/
void lv_vector_dsc_set_blend_mode(lv_vector_dsc_t * dsc, lv_vector_blend_t blend);
/**
* Set fill color for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param color the color to be set in lv_color32_t format
*/
void lv_vector_dsc_set_fill_color32(lv_vector_dsc_t * dsc, lv_color32_t color);
/**
* Set fill color for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param color the color to be set in lv_color_t format
*/
void lv_vector_dsc_set_fill_color(lv_vector_dsc_t * dsc, lv_color_t color);
/**
* Set fill opacity for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param opa the opacity to be set in lv_opa_t format
*/
void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa);
/**
* Set fill rule for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param rule the fill rule to be set in lv_vector_fill_t format
*/
void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule);
/**
* Set fill image for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param img_dsc pointer to a `lv_draw_image_dsc_t` variable
*/
void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc);
/**
* Set fill linear gradient for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param x1 the x for start point
* @param y1 the y for start point
* @param x2 the x for end point
* @param y2 the y for end point
*/
void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2);
/**
* Set fill radial gradient radius for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param cx the x for center of the circle
* @param cy the y for center of the circle
* @param radius the radius for circle
*/
void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius);
/**
* Set fill radial gradient spread for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param spread the gradient spread to be set in lv_vector_gradient_spread_t format
*/
void lv_vector_dsc_set_fill_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread);
/**
* Set fill gradient color stops for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param stops an array of `lv_gradient_stop_t` variables
* @param count the number of stops in the array, range: 0..LV_GRADIENT_MAX_STOPS
*/
void lv_vector_dsc_set_fill_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops,
uint16_t count);
/**
* Set a matrix to current fill transformation matrix
* @param dsc pointer to a vector graphic descriptor
* @param matrix pointer to a matrix
*/
void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix);
/**
* Set stroke color for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param color the color to be set in lv_color32_t format
*/
void lv_vector_dsc_set_stroke_color32(lv_vector_dsc_t * dsc, lv_color32_t color);
/**
* Set stroke color for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param color the color to be set in lv_color_t format
*/
void lv_vector_dsc_set_stroke_color(lv_vector_dsc_t * dsc, lv_color_t color);
/**
* Set stroke opacity for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param opa the opacity to be set in lv_opa_t format
*/
void lv_vector_dsc_set_stroke_opa(lv_vector_dsc_t * dsc, lv_opa_t opa);
/**
* Set stroke line width for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param width the stroke line width
*/
void lv_vector_dsc_set_stroke_width(lv_vector_dsc_t * dsc, float width);
/**
* Set stroke line dash pattern for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param dash_pattern an array of values that specify the segments of dash line
* @param dash_count the length of dash pattern array
*/
void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, uint16_t dash_count);
/**
* Set stroke line cap style for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param cap the line cap to be set in lv_vector_stroke_cap_t format
*/
void lv_vector_dsc_set_stroke_cap(lv_vector_dsc_t * dsc, lv_vector_stroke_cap_t cap);
/**
* Set stroke line join style for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param join the line join to be set in lv_vector_stroke_join_t format
*/
void lv_vector_dsc_set_stroke_join(lv_vector_dsc_t * dsc, lv_vector_stroke_join_t join);
/**
* Set stroke miter limit for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param miter_limit the stroke miter_limit
*/
void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_limit);
/**
* Set stroke linear gradient for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param x1 the x for start point
* @param y1 the y for start point
* @param x2 the x for end point
* @param y2 the y for end point
*/
void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, float x1, float y1, float x2, float y2);
/**
* Set stroke radial gradient for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param cx the x for center of the circle
* @param cy the y for center of the circle
* @param radius the radius for circle
*/
void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, float cx, float cy, float radius);
/**
* Set stroke color stops for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param spread the gradient spread to be set in lv_vector_gradient_spread_t format
*/
void lv_vector_dsc_set_stroke_gradient_spread(lv_vector_dsc_t * dsc, lv_vector_gradient_spread_t spread);
/**
* Set stroke color stops for descriptor
* @param dsc pointer to a vector graphic descriptor
* @param stops an array of `lv_gradient_stop_t` variables
* @param count the number of stops in the array
*/
void lv_vector_dsc_set_stroke_gradient_color_stops(lv_vector_dsc_t * dsc, const lv_gradient_stop_t * stops,
uint16_t count);
/**
* Set a matrix to current stroke transformation matrix
* @param dsc pointer to a vector graphic descriptor
* @param matrix pointer to a matrix
*/
void lv_vector_dsc_set_stroke_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix);
/**
* Set current transformation matrix to identity matrix
* @param dsc pointer to a vector graphic descriptor
*/
void lv_vector_dsc_identity(lv_vector_dsc_t * dsc);
/**
* Change the scale factor of current transformation matrix
* @param dsc pointer to a vector graphic descriptor
* @param scale_x the scale factor for the X direction
* @param scale_y the scale factor for the Y direction
*/
void lv_vector_dsc_scale(lv_vector_dsc_t * dsc, float scale_x, float scale_y);
/**
* Rotate current transformation matrix with origin
* @param dsc pointer to a vector graphic descriptor
* @param degree angle to rotate
*/
void lv_vector_dsc_rotate(lv_vector_dsc_t * dsc, float degree);
/**
* Translate current transformation matrix to new position
* @param dsc pointer to a vector graphic descriptor
* @param tx the amount of translate in x direction
* @param tx the amount of translate in y direction
*/
void lv_vector_dsc_translate(lv_vector_dsc_t * dsc, float tx, float ty);
/**
* Change the skew factor of current transformation matrix
* @param dsc pointer to a vector graphic descriptor
* @param skew_x the skew factor for x direction
* @param skew_y the skew factor for y direction
*/
void lv_vector_dsc_skew(lv_vector_dsc_t * dsc, float skew_x, float skew_y);
/**
* Add a graphic path to the draw list
* @param dsc pointer to a vector graphic descriptor
* @param path pointer to a path
*/
void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path);
/**
* Clear a rectangle area use current fill color
* @param dsc pointer to a vector graphic descriptor
* @param rect the area to clear in the buffer
*/
void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect);
/**
* Draw all the vector graphic paths
* @param dsc pointer to a vector graphic descriptor
*/
void lv_draw_vector(lv_vector_dsc_t * dsc);
/* Traverser for task list */
typedef void (*vector_draw_task_cb)(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc);
#endif /* LV_USE_VECTOR_GRAPHIC */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_DRAW_VECTOR_H */

View File

@@ -1,109 +0,0 @@
/**
* @file lv_draw_vector_private.h
*
*/
#ifndef LV_DRAW_VECTOR_PRIVATE_H
#define LV_DRAW_VECTOR_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_vector.h"
#if LV_USE_VECTOR_GRAPHIC
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct lv_vector_path_t {
lv_vector_path_quality_t quality;
lv_array_t ops;
lv_array_t points;
};
struct lv_vector_gradient_t {
lv_vector_gradient_style_t style;
lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; /**< A gradient stop array */
uint16_t stops_count; /**< The number of used stops in the array */
float x1;
float y1;
float x2;
float y2;
float cx;
float cy;
float cr;
lv_vector_gradient_spread_t spread;
};
struct lv_vector_fill_dsc_t {
lv_vector_draw_style_t style;
lv_color32_t color;
lv_opa_t opa;
lv_vector_fill_t fill_rule;
lv_draw_image_dsc_t img_dsc;
lv_vector_gradient_t gradient;
lv_matrix_t matrix;
};
struct lv_vector_stroke_dsc_t {
lv_vector_draw_style_t style;
lv_color32_t color;
lv_opa_t opa;
float width;
lv_array_t dash_pattern;
lv_vector_stroke_cap_t cap;
lv_vector_stroke_join_t join;
uint16_t miter_limit;
lv_vector_gradient_t gradient;
lv_matrix_t matrix;
};
struct lv_vector_draw_dsc_t {
lv_vector_fill_dsc_t fill_dsc;
lv_vector_stroke_dsc_t stroke_dsc;
lv_matrix_t matrix;
lv_vector_blend_t blend_mode;
lv_area_t scissor_area;
};
struct lv_draw_vector_task_dsc_t {
lv_draw_dsc_base_t base;
lv_ll_t * task_list; /*draw task list.*/
};
struct lv_vector_dsc_t {
lv_layer_t * layer;
lv_vector_draw_dsc_t current_dsc;
/* private data */
lv_draw_vector_task_dsc_t tasks;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_vector_for_each_destroy_tasks(lv_ll_t * task_list, vector_draw_task_cb cb, void * data);
/**********************
* MACROS
**********************/
#endif /* LV_USE_VECTOR_GRAPHIC */
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VECTOR_PRIVATE_H*/

View File

@@ -1,415 +0,0 @@
/**
* @file lv_image_decoder.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_image_decoder_private.h"
#include "../misc/lv_assert.h"
#include "../draw/lv_draw_image.h"
#include "../misc/lv_ll.h"
#include "../stdlib/lv_string.h"
#include "../core/lv_global.h"
/*********************
* DEFINES
*********************/
#define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll)
#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache)
#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache)
#define image_cache_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static uint32_t img_width_to_stride(lv_image_header_t * header);
/**
* Get the header info of an image source, and return the a pointer to the decoder that can open it.
* @param dsc Image descriptor containing the source and type of the image and other info.
* @param header The header of the image
* @return The decoder that can open the image source or NULL if not found (or can't open it).
*/
static lv_image_decoder_t * image_decoder_get_info(lv_image_decoder_dsc_t * dsc, lv_image_header_t * header);
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the image decoder module
*/
void lv_image_decoder_init(uint32_t image_cache_size, uint32_t image_header_count)
{
lv_ll_init(img_decoder_ll_p, sizeof(lv_image_decoder_t));
/*Initialize the cache*/
lv_image_cache_init(image_cache_size);
lv_image_header_cache_init(image_header_count);
}
/**
* Deinitialize the image decoder module
*/
void lv_image_decoder_deinit(void)
{
lv_cache_destroy(img_cache_p, NULL);
lv_cache_destroy(img_header_cache_p, NULL);
lv_ll_clear(img_decoder_ll_p);
}
lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header)
{
lv_image_decoder_dsc_t dsc;
lv_memzero(&dsc, sizeof(lv_image_decoder_dsc_t));
dsc.src = src;
dsc.src_type = lv_image_src_get_type(src);
lv_image_decoder_t * decoder = image_decoder_get_info(&dsc, header);
if(decoder == NULL) return LV_RESULT_INVALID;
return LV_RESULT_OK;
}
lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args)
{
lv_memzero(dsc, sizeof(lv_image_decoder_dsc_t));
if(src == NULL) return LV_RESULT_INVALID;
dsc->src = src;
dsc->src_type = lv_image_src_get_type(src);
if(lv_image_cache_is_enabled()) {
dsc->cache = img_cache_p;
/*Try cache first, unless we are told to ignore cache.*/
if(!(args && args->no_cache)) {
/*
* Check the cache first
* If the image is found in the cache, just return it.*/
if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK;
}
}
/*Find the decoder that can open the image source, and get the header info in the same time.*/
dsc->decoder = image_decoder_get_info(dsc, &dsc->header);
if(dsc->decoder == NULL) return LV_RESULT_INVALID;
/*Make a copy of args*/
dsc->args = args ? *args : (lv_image_decoder_args_t) {
.stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1,
.premultiply = false,
.no_cache = false,
.use_indexed = false,
.flush_cache = false,
};
/*
* We assume that if a decoder can get the info, it can open the image.
* If decoder open failed, free the source and return error.
* If decoder open succeed, add the image to cache if enabled.
* */
lv_result_t res = dsc->decoder->open_cb(dsc->decoder, dsc);
/* Flush the D-Cache if enabled and the image was successfully opened */
if(dsc->args.flush_cache && res == LV_RESULT_OK && dsc->decoded != NULL) {
lv_draw_buf_flush_cache(dsc->decoded, NULL);
LV_LOG_INFO("Flushed D-cache: src %p (%s) (W%d x H%d, data: %p cf: %d)",
src,
dsc->src_type == LV_IMAGE_SRC_FILE ? (const char *)src : "c-array",
dsc->decoded->header.w,
dsc->decoded->header.h,
(void *)dsc->decoded->data,
dsc->decoded->header.cf);
}
return res;
}
lv_result_t lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area,
lv_area_t * decoded_area)
{
lv_result_t res = LV_RESULT_INVALID;
if(dsc->decoder->get_area_cb) res = dsc->decoder->get_area_cb(dsc->decoder, dsc, full_area, decoded_area);
return res;
}
void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc)
{
if(dsc->decoder) {
if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc);
if(lv_image_cache_is_enabled() && dsc->cache && dsc->cache_entry) {
/*Decoded data is in cache, release it from cache's callback*/
lv_cache_release(dsc->cache, dsc->cache_entry, NULL);
}
}
}
/**
* Create a new image decoder
* @return pointer to the new image decoder
*/
lv_image_decoder_t * lv_image_decoder_create(void)
{
lv_image_decoder_t * decoder;
decoder = lv_ll_ins_head(img_decoder_ll_p);
LV_ASSERT_MALLOC(decoder);
if(decoder == NULL) return NULL;
lv_memzero(decoder, sizeof(lv_image_decoder_t));
return decoder;
}
void lv_image_decoder_delete(lv_image_decoder_t * decoder)
{
lv_ll_remove(img_decoder_ll_p, decoder);
lv_free(decoder);
}
lv_image_decoder_t * lv_image_decoder_get_next(lv_image_decoder_t * decoder)
{
if(decoder == NULL)
return lv_ll_get_head(img_decoder_ll_p);
else
return lv_ll_get_next(img_decoder_ll_p, decoder);
}
void lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder, lv_image_decoder_info_f_t info_cb)
{
decoder->info_cb = info_cb;
}
void lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder, lv_image_decoder_open_f_t open_cb)
{
decoder->open_cb = open_cb;
}
void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_decoder_get_area_cb_t get_area_cb)
{
decoder->get_area_cb = get_area_cb;
}
void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb)
{
decoder->close_cb = close_cb;
}
lv_cache_entry_t * lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder,
lv_image_cache_data_t * search_key,
const lv_draw_buf_t * decoded, void * user_data)
{
lv_cache_entry_t * cache_entry = lv_cache_add(img_cache_p, search_key, NULL);
if(cache_entry == NULL) {
return NULL;
}
lv_image_cache_data_t * cached_data;
cached_data = lv_cache_entry_get_data(cache_entry);
/*Set the cache entry to decoder data*/
cached_data->decoded = decoded;
if(cached_data->src_type == LV_IMAGE_SRC_FILE) {
cached_data->src = lv_strdup(cached_data->src);
}
cached_data->user_data = user_data; /*Need to free data on cache invalidate instead of decoder_close*/
cached_data->decoder = decoder;
return cache_entry;
}
lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_draw_buf_t * decoded)
{
if(decoded == NULL) return NULL; /*No need to adjust*/
lv_image_decoder_args_t * args = &dsc->args;
if(args->stride_align && decoded->header.cf != LV_COLOR_FORMAT_RGB565A8) {
uint32_t stride_expect = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf);
if(decoded->header.stride != stride_expect) {
LV_LOG_TRACE("Stride mismatch");
lv_result_t res = lv_draw_buf_adjust_stride(decoded, stride_expect);
if(res != LV_RESULT_OK) {
lv_draw_buf_t * aligned = lv_draw_buf_create_ex(image_cache_draw_buf_handlers, decoded->header.w, decoded->header.h,
decoded->header.cf, stride_expect);
if(aligned == NULL) {
LV_LOG_ERROR("No memory for Stride adjust.");
return NULL;
}
lv_draw_buf_copy(aligned, NULL, decoded, NULL);
decoded = aligned;
}
}
}
/*Premultiply alpha channel*/
if(args->premultiply
&& !LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoded->header.cf)
&& lv_color_format_has_alpha(decoded->header.cf)
&& !lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_PREMULTIPLIED) /*Hasn't done yet*/
) {
LV_LOG_TRACE("Alpha premultiply.");
if(lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_MODIFIABLE)) {
/*Do it directly*/
lv_draw_buf_premultiply(decoded);
}
else {
decoded = lv_draw_buf_dup_ex(image_cache_draw_buf_handlers, decoded);
if(decoded == NULL) {
LV_LOG_ERROR("No memory for premultiplying.");
return NULL;
}
lv_draw_buf_premultiply(decoded);
}
}
return decoded;
}
/**********************
* STATIC FUNCTIONS
**********************/
static lv_image_decoder_t * image_decoder_get_info(lv_image_decoder_dsc_t * dsc, lv_image_header_t * header)
{
lv_memzero(header, sizeof(lv_image_header_t));
const void * src = dsc->src;
lv_image_src_t src_type = dsc->src_type;
if(src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = src;
if(img_dsc->data == NULL) return NULL;
}
if(src_type == LV_IMAGE_SRC_FILE) LV_LOG_TRACE("Try to find decoder for %s", (const char *)src);
else LV_LOG_TRACE("Try to find decoder for %p", src);
lv_image_decoder_t * decoder;
bool is_header_cache_enabled = lv_image_header_cache_is_enabled();
if(is_header_cache_enabled && src_type == LV_IMAGE_SRC_FILE) {
lv_image_header_cache_data_t search_key;
search_key.src_type = src_type;
search_key.src = src;
lv_cache_entry_t * entry = lv_cache_acquire(img_header_cache_p, &search_key, NULL);
if(entry) {
lv_image_header_cache_data_t * cached_data = lv_cache_entry_get_data(entry);
*header = cached_data->header;
decoder = cached_data->decoder;
lv_cache_release(img_header_cache_p, entry, NULL);
LV_LOG_TRACE("Found decoder %s in header cache", decoder->name);
return decoder;
}
}
if(src_type == LV_IMAGE_SRC_FILE) {
lv_fs_res_t fs_res = lv_fs_open(&dsc->file, src, LV_FS_MODE_RD);
if(fs_res != LV_FS_RES_OK) {
LV_LOG_ERROR("File open failed: %" LV_PRIu32, (uint32_t)fs_res);
return NULL;
}
}
/*Search the decoders*/
lv_image_decoder_t * decoder_prev = NULL;
LV_LL_READ(img_decoder_ll_p, decoder) {
/*Info and Open callbacks are required*/
if(decoder->info_cb && decoder->open_cb) {
lv_fs_seek(&dsc->file, 0, LV_FS_SEEK_SET);
lv_result_t res = decoder->info_cb(decoder, dsc, header);
if(decoder_prev) LV_LOG_TRACE("Can't open image with decoder %s. Trying next decoder.", decoder_prev->name);
if(res == LV_RESULT_OK) {
if(header->stride == 0) {
LV_LOG_INFO("Image decoder didn't set stride. Calculate it from width.");
header->stride = img_width_to_stride(header);
}
break;
}
decoder_prev = decoder;
}
}
if(decoder == NULL) LV_LOG_TRACE("No decoder found");
else LV_LOG_TRACE("Found decoder %s", decoder->name);
if(src_type == LV_IMAGE_SRC_FILE) {
lv_fs_close(&dsc->file);
}
if(is_header_cache_enabled && src_type == LV_IMAGE_SRC_FILE && decoder) {
lv_cache_entry_t * entry;
lv_image_header_cache_data_t search_key;
search_key.src_type = src_type;
search_key.src = lv_strdup(src);
search_key.decoder = decoder;
search_key.header = *header;
entry = lv_cache_add(img_header_cache_p, &search_key, NULL);
if(entry == NULL) {
if(src_type == LV_IMAGE_SRC_FILE) lv_free((void *)search_key.src);
return NULL;
}
lv_cache_release(img_header_cache_p, entry, NULL);
}
return decoder;
}
static uint32_t img_width_to_stride(lv_image_header_t * header)
{
if(header->cf == LV_COLOR_FORMAT_RGB565A8) {
return header->w * 2;
}
else {
return ((uint32_t)header->w * lv_color_format_get_bpp(header->cf) + 7) >> 3;
}
}
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
{
lv_cache_t * cache = dsc->cache;
lv_image_cache_data_t search_key;
search_key.src_type = dsc->src_type;
search_key.src = dsc->src;
lv_cache_entry_t * entry = lv_cache_acquire(cache, &search_key, NULL);
if(entry) {
lv_image_cache_data_t * cached_data = lv_cache_entry_get_data(entry);
dsc->decoded = cached_data->decoded;
dsc->decoder = (lv_image_decoder_t *)cached_data->decoder;
dsc->cache_entry = entry; /*Save the cache to release it in decoder_close*/
return LV_RESULT_OK;
}
return LV_RESULT_INVALID;
}

View File

@@ -1,194 +0,0 @@
/**
* @file lv_image_decoder.h
*
*/
#ifndef LV_IMAGE_DECODER_H
#define LV_IMAGE_DECODER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include "lv_draw_buf.h"
#include "../misc/lv_fs.h"
#include "../misc/lv_types.h"
#include "../misc/lv_area.h"
#include "../misc/cache/lv_cache.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**
* Source of image.*/
typedef enum {
LV_IMAGE_SRC_VARIABLE, /** Binary/C variable*/
LV_IMAGE_SRC_FILE, /** File in filesystem*/
LV_IMAGE_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/
LV_IMAGE_SRC_UNKNOWN, /** Unknown source*/
} lv_image_src_t;
/**
* Get info from an image and store in the `header`
* @param decoder pointer to decoder object
* @param dsc pointer to decoder descriptor
* @param header store the info here
* @return LV_RESULT_OK: info written correctly; LV_RESULT_INVALID: failed
*/
typedef lv_result_t (*lv_image_decoder_info_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
lv_image_header_t * header);
/**
* Open an image for decoding. Prepare it as it is required to read it later
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it.
*/
typedef lv_result_t (*lv_image_decoder_open_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
/**
* Decode `full_area` pixels incrementally by calling in a loop. Set `decoded_area` values to `LV_COORD_MIN` on first call.
* Required only if the "open" function can't return with the whole decoded pixel array.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
* @param full_area input parameter. the full area to decode after enough subsequent calls
* @param decoded_area input+output parameter. set the values to `LV_COORD_MIN` for the first call and to reset decoding.
* the decoded area is stored here after each call.
* @return LV_RESULT_OK: ok; LV_RESULT_INVALID: failed or there is nothing left to decode
*/
typedef lv_result_t (*lv_image_decoder_get_area_cb_t)(lv_image_decoder_t * decoder,
lv_image_decoder_dsc_t * dsc,
const lv_area_t * full_area, lv_area_t * decoded_area);
/**
* Close the pending decoding. Free resources etc.
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
*/
typedef void (*lv_image_decoder_close_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Get information about an image.
* Try the created image decoder one by one. Once one is able to get info that info will be used.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register()`)
* 2) Variable: Pointer to an `lv_image_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param header the image info will be stored here
* @return LV_RESULT_OK: success; LV_RESULT_INVALID: wasn't able to get info about the image
*/
lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header);
/**
* Open an image.
* Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc`
* @param dsc describes a decoding session. Simply a pointer to an `lv_image_decoder_dsc_t` variable.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register())`)
* 2) Variable: Pointer to an `lv_image_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param args args about how the image should be opened.
* @return LV_RESULT_OK: opened the image. `dsc->decoded` and `dsc->header` are set.
* LV_RESULT_INVALID: none of the registered image decoders were able to open the image.
*/
lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args);
/**
* Decode `full_area` pixels incrementally by calling in a loop. Set `decoded_area` to `LV_COORD_MIN` on first call.
* @param dsc image decoder descriptor
* @param full_area input parameter. the full area to decode after enough subsequent calls
* @param decoded_area input+output parameter. set the values to `LV_COORD_MIN` for the first call and to reset decoding.
* the decoded area is stored here after each call.
* @return LV_RESULT_OK: success; LV_RESULT_INVALID: an error occurred or there is nothing left to decode
*/
lv_result_t lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area,
lv_area_t * decoded_area);
/**
* Close a decoding session
* @param dsc pointer to `lv_image_decoder_dsc_t` used in `lv_image_decoder_open`
*/
void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc);
/**
* Create a new image decoder
* @return pointer to the new image decoder
*/
lv_image_decoder_t * lv_image_decoder_create(void);
/**
* Delete an image decoder
* @param decoder pointer to an image decoder
*/
void lv_image_decoder_delete(lv_image_decoder_t * decoder);
/**
* Get the next image decoder in the linked list of image decoders
* @param decoder pointer to an image decoder or NULL to get the first one
* @return the next image decoder or NULL if no more image decoder exists
*/
lv_image_decoder_t * lv_image_decoder_get_next(lv_image_decoder_t * decoder);
/**
* Set a callback to get information about the image
* @param decoder pointer to an image decoder
* @param info_cb a function to collect info about an image (fill an `lv_image_header_t` struct)
*/
void lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder, lv_image_decoder_info_f_t info_cb);
/**
* Set a callback to open an image
* @param decoder pointer to an image decoder
* @param open_cb a function to open an image
*/
void lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder, lv_image_decoder_open_f_t open_cb);
/**
* Set a callback to a decoded line of an image
* @param decoder pointer to an image decoder
* @param read_line_cb a function to read a line of an image
*/
void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_decoder_get_area_cb_t read_line_cb);
/**
* Set a callback to close a decoding session. E.g. close files and free other resources.
* @param decoder pointer to an image decoder
* @param close_cb a function to close a decoding session
*/
void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb);
lv_cache_entry_t * lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder,
lv_image_cache_data_t * search_key,
const lv_draw_buf_t * decoded, void * user_data);
/**
* Check the decoded image, make any modification if decoder `args` requires.
* @note A new draw buf will be allocated if provided `decoded` is not modifiable or stride mismatch etc.
* @param dsc pointer to a decoder descriptor
* @param decoded pointer to a decoded image to post process to meet dsc->args requirement.
* @return post processed draw buffer, when it differs with `decoded`, it's newly allocated.
*/
lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_draw_buf_t * decoded);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMAGE_DECODER_H*/

View File

@@ -1,142 +0,0 @@
/**
* @file lv_image_decoder_private.h
*
*/
#ifndef LV_IMAGE_DECODER_PRIVATE_H
#define LV_IMAGE_DECODER_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_image_decoder.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**
* Image decoder args.
* It determines how to decoder an image, e.g. whether to premultiply the alpha or not.
* It should be passed to lv_img_decoder_open() function. If NULL is provided, default
* args are used.
*
* Default args:
* all field are zero or false.
*/
struct lv_image_decoder_args_t {
bool stride_align; /**< Whether stride should be aligned */
bool premultiply; /**< Whether image should be premultiplied or not after decoding */
bool no_cache; /**< When set, decoded image won't be put to cache, and decoder open will also ignore cache. */
bool use_indexed; /**< Decoded indexed image as is. Convert to ARGB8888 if false. */
bool flush_cache; /**< Whether to flush the data cache after decoding */
};
struct lv_image_decoder_t {
lv_image_decoder_info_f_t info_cb;
lv_image_decoder_open_f_t open_cb;
lv_image_decoder_get_area_cb_t get_area_cb;
lv_image_decoder_close_f_t close_cb;
const char * name;
void * user_data;
};
struct lv_image_cache_data_t {
lv_cache_slot_size_t slot;
const void * src;
lv_image_src_t src_type;
const lv_draw_buf_t * decoded;
const lv_image_decoder_t * decoder;
void * user_data;
};
struct lv_image_header_cache_data_t {
const void * src;
lv_image_src_t src_type;
lv_image_header_t header;
lv_image_decoder_t * decoder;
};
/**Describe an image decoding session. Stores data about the decoding*/
struct lv_image_decoder_dsc_t {
/**The decoder which was able to open the image source*/
lv_image_decoder_t * decoder;
/**A copy of parameters of how this image is decoded*/
lv_image_decoder_args_t args;
/**The image source. A file path like "S:my_img.png" or pointer to an `lv_image_dsc_t` variable*/
const void * src;
/**Type of the source: file or variable. Can be set in `open` function if required*/
lv_image_src_t src_type;
lv_fs_file_t file;
/**Info about the opened image: color format, size, etc. MUST be set in `open` function*/
lv_image_header_t header;
/** Pointer to a draw buffer where the image's data (pixels) are stored in a decoded, plain format.
* MUST be set in `open` or `get_area_cb`function*/
const lv_draw_buf_t * decoded;
const lv_color32_t * palette;
uint32_t palette_size;
/** How much time did it take to open the image. [ms]
* If not set `lv_image_cache` will measure and set the time to open*/
uint32_t time_to_open;
/**A text to display instead of the image when the image can't be opened.
* Can be set in `open` function or set NULL.*/
const char * error_msg;
lv_cache_t * cache;
/**Point to cache entry information*/
lv_cache_entry_t * cache_entry;
/**Store any custom data here is required*/
void * user_data;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize the image decoder module
* @param image_cache_size Image cache size in bytes. 0 to disable cache.
* @param image_header_count Number of header cache entries. 0 to disable header cache.
*/
void lv_image_decoder_init(uint32_t image_cache_size, uint32_t image_header_count);
/**
* Deinitialize the image decoder module
*/
void lv_image_decoder_deinit(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMAGE_DECODER_PRIVATE_H*/

View File

@@ -1,141 +0,0 @@
/**
* @file lv_image_dsc.h
*
*/
#ifndef LV_IMAGE_DSC_H
#define LV_IMAGE_DSC_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
/*********************
* DEFINES
*********************/
/** Magic number for lvgl image, 9 means lvgl version 9
* It must be neither a valid ASCII character nor larger than 0x80. See `lv_image_src_get_type`.
*/
#define LV_IMAGE_HEADER_MAGIC (0x19)
LV_EXPORT_CONST_INT(LV_IMAGE_HEADER_MAGIC);
/**********************
* TYPEDEFS
**********************/
typedef enum lv_image_flags_t {
/**
* For RGB map of the image data, mark if it's pre-multiplied with alpha.
* For indexed image, this bit indicated palette data is pre-multiplied with alpha.
*/
LV_IMAGE_FLAGS_PREMULTIPLIED = 0x0001,
/**
* The image data is compressed, so decoder needs to decode image firstly.
* If this flag is set, the whole image will be decompressed upon decode, and
* `get_area_cb` won't be necessary.
*/
LV_IMAGE_FLAGS_COMPRESSED = 0x0008,
/*Below flags are applicable only for draw buffer header.*/
/**
* The image is allocated from heap, thus should be freed after use.
*/
LV_IMAGE_FLAGS_ALLOCATED = 0x0010,
/**
* If the image data is malloced and can be processed in place.
* In image decoder post processing, this flag means we modify it in-place.
*/
LV_IMAGE_FLAGS_MODIFIABLE = 0x0020,
/**
* Flags reserved for user, lvgl won't use these bits.
*/
LV_IMAGE_FLAGS_USER1 = 0x0100,
LV_IMAGE_FLAGS_USER2 = 0x0200,
LV_IMAGE_FLAGS_USER3 = 0x0400,
LV_IMAGE_FLAGS_USER4 = 0x0800,
LV_IMAGE_FLAGS_USER5 = 0x1000,
LV_IMAGE_FLAGS_USER6 = 0x2000,
LV_IMAGE_FLAGS_USER7 = 0x4000,
LV_IMAGE_FLAGS_USER8 = 0x8000,
} lv_image_flags_t;
typedef enum {
LV_IMAGE_COMPRESS_NONE = 0,
LV_IMAGE_COMPRESS_RLE, /**< LVGL custom RLE compression */
LV_IMAGE_COMPRESS_LZ4,
} lv_image_compress_t;
#if LV_BIG_ENDIAN_SYSTEM
typedef struct {
uint32_t reserved_2: 16; /**< Reserved to be used later*/
uint32_t stride: 16; /**< Number of bytes in a row*/
uint32_t h: 16;
uint32_t w: 16;
uint32_t flags: 16; /**< Image flags, see `lv_image_flags_t`*/
uint32_t cf : 8; /**< Color format: See `lv_color_format_t`*/
uint32_t magic: 8; /**< Magic number. Must be LV_IMAGE_HEADER_MAGIC*/
} lv_image_header_t;
#else
typedef struct {
uint32_t magic: 8; /**< Magic number. Must be LV_IMAGE_HEADER_MAGIC*/
uint32_t cf : 8; /**< Color format: See `lv_color_format_t`*/
uint32_t flags: 16; /**< Image flags, see `lv_image_flags_t`*/
uint32_t w: 16;
uint32_t h: 16;
uint32_t stride: 16; /**< Number of bytes in a row*/
uint32_t reserved_2: 16; /**< Reserved to be used later*/
} lv_image_header_t;
#endif
typedef struct {
void * buf;
uint32_t stride; /**< Number of bytes in a row*/
} lv_yuv_plane_t;
typedef union {
lv_yuv_plane_t yuv; /**< packed format*/
struct {
lv_yuv_plane_t y;
lv_yuv_plane_t u;
lv_yuv_plane_t v;
} planar; /**< planar format with 3 plane*/
struct {
lv_yuv_plane_t y;
lv_yuv_plane_t uv;
} semi_planar; /**< planar format with 2 plane*/
} lv_yuv_buf_t;
/**
* Struct to describe a constant image resource.
* It's similar to lv_draw_buf_t, but the data is constant.
*/
typedef struct {
lv_image_header_t header; /**< A header describing the basics of the image*/
uint32_t data_size; /**< Size of the image in bytes*/
const uint8_t * data; /**< Pointer to the data of the image*/
const void * reserved; /**< A reserved field to make it has same size as lv_draw_buf_t*/
} lv_image_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_IMAGE_DSC_H*/

View File

@@ -1,117 +0,0 @@
/**
* @file lv_draw_buf_pxp.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP
#include "../../lv_draw_buf_private.h"
#include "lv_pxp_cfg.h"
#include "lv_pxp_utils.h"
#include "lvgl_support.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_buf_pxp_init_handlers(void)
{
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
lv_draw_buf_handlers_t * font_handlers = lv_draw_buf_get_font_handlers();
lv_draw_buf_handlers_t * image_handlers = lv_draw_buf_get_image_handlers();
handlers->invalidate_cache_cb = _invalidate_cache;
font_handlers->invalidate_cache_cb = _invalidate_cache;
image_handlers->invalidate_cache_cb = _invalidate_cache;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
const lv_image_header_t * header = &draw_buf->header;
uint32_t stride = header->stride;
lv_color_format_t cf = header->cf;
if(area->y1 == 0) {
uint32_t size = stride * lv_area_get_height(area);
/* Invalidate full buffer. */
DEMO_CleanInvalidateCacheByAddr((void *)draw_buf->data, size);
return;
}
const uint8_t * buf_u8 = draw_buf->data;
/* ARM require a 32 byte aligned address. */
uint8_t align_bytes = 32;
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
uint16_t offset_x = 0;
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
offset_x = area->x1 - shift_x;
buf_u8 += (shift_x * bits_per_pixel) / 8;
}
if(area->y1) {
uint16_t shift_y = area->y1;
buf_u8 += shift_y * stride;
}
/* Area to clear can start from a different offset in buffer.
* Invalidate the area line by line.
*/
uint16_t line_pixels = offset_x + lv_area_get_width(area);
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
uint16_t area_height = lv_area_get_height(area);
for(uint16_t y = 0; y < area_height; y++) {
const void * line_addr = buf_u8 + y * stride;
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
}
}
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,498 +0,0 @@
/**
* @file lv_draw_pxp.c
*
*/
/**
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "lv_pxp_cfg.h"
#include "lv_pxp_utils.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
*********************/
#define DRAW_UNIT_ID_PXP 3
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/*
* Evaluate a task and set the score and preferred PXP unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
*/
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/*
* Dispatch a task to the PXP unit.
* Return 1 if task was dispatched, 0 otherwise (task not supported).
*/
static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/*
* Delete the PXP draw unit.
*/
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit);
#if LV_USE_PXP_DRAW_THREAD
static void _pxp_render_thread_cb(void * ptr);
#endif
static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u);
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_init(void)
{
lv_pxp_init();
#if LV_USE_DRAW_PXP
lv_draw_buf_pxp_init_handlers();
lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
#if LV_USE_PXP_DRAW_THREAD
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
#endif
#endif /*LV_USE_DRAW_PXP*/
}
void lv_draw_pxp_deinit(void)
{
lv_pxp_deinit();
}
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
lv_color_format_t cf)
{
lv_pxp_reset();
/* Convert rotation angle
* To be in sync with CPU, the received angle is counterclockwise
* and the PXP constants are for clockwise rotation
*
* counterclockwise clockwise
* LV_DISPLAY_ROTATION_90 -> kPXP_Rotate270
* LV_DISPLAY_ROTATION_270 -> kPXP_Rotate90
*/
pxp_rotate_degree_t pxp_rotation;
switch(rotation) {
case LV_DISPLAY_ROTATION_0:
pxp_rotation = kPXP_Rotate0;
break;
case LV_DISPLAY_ROTATION_270:
pxp_rotation = kPXP_Rotate90;
break;
case LV_DISPLAY_ROTATION_180:
pxp_rotation = kPXP_Rotate180;
break;
case LV_DISPLAY_ROTATION_90:
pxp_rotation = kPXP_Rotate270;
break;
default:
pxp_rotation = kPXP_Rotate0;
break;
}
PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_rotation, kPXP_FlipDisable);
/*Simple blit, no effect - Disable PS buffer*/
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = pxp_get_as_px_format(cf),
.bufferAddr = (uint32_t)src_buf,
.pitchBytes = src_stride
};
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_width - 1U, src_height - 1U);
PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false);
/*Output buffer.*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = pxp_get_out_px_format(cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)dest_buf,
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = src_width,
.height = src_height
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
lv_pxp_run();
}
/**********************
* STATIC FUNCTIONS
**********************/
#if LV_USE_DRAW_PXP
static inline bool _pxp_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 _pxp_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:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static bool _pxp_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc)
{
const lv_image_dsc_t * img_dsc = draw_dsc->src;
bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN);
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
/* Recolor and transformation are not supported at the same time. */
if(has_recolor && has_transform)
return false;
bool has_opa = (draw_dsc->opa < (lv_opa_t)LV_OPA_MAX);
bool src_has_alpha = (img_dsc->header.cf == LV_COLOR_FORMAT_ARGB8888);
/*
* Recolor or transformation for images w/ opa or alpha channel can't
* be obtained in a single PXP configuration. Two steps are required.
*/
if((has_recolor || has_transform) && (has_opa || src_has_alpha))
return false;
/* PXP can only rotate at 90x angles. */
if(draw_dsc->rotation % 900)
return false;
/*
* PXP is set to process 16x16 blocks to optimize the system for memory
* bandwidth and image processing time.
* The output engine essentially truncates any output pixels after the
* desired number of pixels has been written.
* When rotating a source image and the output is not divisible by the block
* size, the incorrect pixels could be truncated and the final output image
* can look shifted.
*
* No combination of rotate with flip, scaling or decimation is possible
* if buffer is unaligned.
*/
if(has_transform && (img_dsc->header.w % 16 || img_dsc->header.h % 16))
return false;
return true;
}
static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
{
LV_UNUSED(u);
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
if(!_pxp_dest_cf_supported(draw_dsc_base->layer->color_format))
return 0;
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL: {
const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc;
/* Most simple case: just a plain rectangle (no radius, no gradient). */
if((draw_dsc->radius != 0) || (draw_dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
}
return 1;
}
case LV_DRAW_TASK_TYPE_LAYER: {
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
if(!_pxp_src_cf_supported(layer_to_draw->color_format))
return 0;
if(!_pxp_draw_img_supported(draw_dsc))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
}
return 1;
}
case LV_DRAW_TASK_TYPE_IMAGE: {
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
const lv_image_dsc_t * img_dsc = draw_dsc->src;
if(draw_dsc->tile)
return 0;
if((!_pxp_src_cf_supported(img_dsc->header.cf)) ||
(!pxp_buf_aligned(img_dsc->data, img_dsc->header.stride)))
return 0;
if(!_pxp_draw_img_supported(draw_dsc))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
}
return 1;
}
default:
return 0;
}
return 0;
}
static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{
lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit;
/* Return immediately if it's busy with draw task. */
if(draw_pxp_unit->task_act)
return 0;
/* Try to get an ready to draw. */
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_PXP);
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP)
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;
draw_pxp_unit->base_unit.target_layer = layer;
draw_pxp_unit->base_unit.clip_area = &t->clip_area;
draw_pxp_unit->task_act = t;
#if LV_USE_PXP_DRAW_THREAD
/* Let the render thread work. */
if(draw_pxp_unit->inited)
lv_thread_sync_signal(&draw_pxp_unit->sync);
#else
_pxp_execute_drawing(draw_pxp_unit);
draw_pxp_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
draw_pxp_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();
#endif
return 1;
}
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit)
{
#if LV_USE_PXP_DRAW_THREAD
lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit;
LV_LOG_INFO("Cancel PXP draw thread.");
draw_pxp_unit->exit_status = true;
if(draw_pxp_unit->inited)
lv_thread_sync_signal(&draw_pxp_unit->sync);
lv_result_t res = lv_thread_delete(&draw_pxp_unit->thread);
return res;
#else
LV_UNUSED(draw_unit);
return 0;
#endif
}
static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
lv_layer_t * layer = draw_unit->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
lv_area_t draw_area;
if(!lv_area_intersect(&draw_area, &t->area, draw_unit->clip_area))
return; /*Fully clipped, nothing to do*/
/* Make area relative to the buffer */
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
/* Invalidate only the drawing area */
lv_draw_buf_invalidate_cache(draw_buf, &draw_area);
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL:
lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_LAYER:
lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area);
break;
default:
break;
}
#if LV_USE_PARALLEL_DRAW_DEBUG
/*Layers manage it for themselves*/
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
lv_area_t draw_area;
if(!lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
return;
int32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_palette_main(idx % LV_PALETTE_LAST);
rect_dsc.border_color = rect_dsc.bg_color;
rect_dsc.bg_opa = LV_OPA_10;
rect_dsc.border_opa = LV_OPA_80;
rect_dsc.border_width = 1;
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.y1 = draw_area.y1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y1 + txt_size.y - 1;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_color_white();
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_black();
label_dsc.text = buf;
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
}
#endif
}
#if LV_USE_PXP_DRAW_THREAD
static void _pxp_render_thread_cb(void * ptr)
{
lv_draw_pxp_unit_t * u = ptr;
lv_thread_sync_init(&u->sync);
u->inited = true;
while(1) {
/* Wait for sync if there is no task set. */
while(u->task_act == NULL) {
if(u->exit_status)
break;
lv_thread_sync_wait(&u->sync);
}
if(u->exit_status) {
LV_LOG_INFO("Ready to exit PXP draw thread.");
break;
}
_pxp_execute_drawing(u);
/* Signal the ready state to dispatcher. */
u->task_act->state = LV_DRAW_TASK_STATE_READY;
/* Cleanup. */
u->task_act = NULL;
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
lv_draw_dispatch_request();
}
u->inited = false;
lv_thread_sync_delete(&u->sync);
LV_LOG_INFO("Exit PXP draw thread.");
}
#endif
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,75 +0,0 @@
/**
* @file lv_draw_pxp.h
*
*/
/**
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_DRAW_PXP_H
#define LV_DRAW_PXP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "../../sw/lv_draw_sw_private.h"
#include "../../../misc/lv_area_private.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_unit_t lv_draw_pxp_unit_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_pxp_init(void);
void lv_draw_pxp_deinit(void);
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
lv_color_format_t cf);
#if LV_USE_DRAW_PXP
void lv_draw_buf_pxp_init_handlers(void);
void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_PXP_H*/

View File

@@ -1,149 +0,0 @@
/**
* @file lv_draw_pxp_fill.c
*
*/
/**
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP
#include "lv_pxp_cfg.h"
#include "lv_pxp_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -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*/
_pxp_fill(draw_buf->data, &blend_area, draw_buf->header.stride, draw_buf->header.cf, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc)
{
int32_t dest_w = lv_area_get_width(dest_area);
int32_t dest_h = lv_area_get_height(dest_area);
lv_pxp_reset();
uint8_t px_size = lv_color_format_get_size(dest_cf);
/*OUT buffer configure*/
pxp_output_buffer_config_t outputConfig = {
.pixelFormat = pxp_get_out_px_format(dest_cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + px_size * dest_area->x1),
.buffer1Addr = (uint32_t)NULL,
.pitchBytes = dest_stride,
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(PXP_ID, &outputConfig);
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
/*Simple color fill without opacity - AS disabled*/
PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
}
else {
/*Fill with opacity - AS used as source (same as OUT)*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = pxp_get_as_px_format(dest_cf),
.bufferAddr = outputConfig.buffer0Addr,
.pitchBytes = outputConfig.pitchBytes
};
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*Disable PS, use as color generator*/
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->color));
/**
* Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff).
*
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
* srcFactorMode is actually applied on PS alpha value
* dstFactorMode is actually applied on AS alpha value
*/
pxp_porter_duff_config_t pdConfig = {
.enable = 1,
.dstColorMode = kPXP_PorterDuffColorNoAlpha,
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.dstFactorMode = kPXP_PorterDuffFactorStraight,
.srcFactorMode = (dsc->opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed,
.dstGlobalAlpha = dsc->opa,
.srcGlobalAlpha = dsc->opa,
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
.srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/
};
PXP_SetPorterDuffConfig(PXP_ID, &pdConfig);
lv_pxp_run();
}
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,367 +0,0 @@
/**
* @file lv_draw_pxp_img.c
*
*/
/**
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP
#include "lv_pxp_cfg.h"
#include "lv_pxp_utils.h"
#include <math.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/* Blit w/ recolor for images w/o opa and alpha channel */
static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc);
/* Blit w/ transformation for images w/o opa and alpha channel */
static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc);
/* Blit simple w/ opa and alpha channel */
static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, lv_opa_t opa);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
const lv_image_dsc_t * img_dsc = dsc->src;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
if(has_transform)
lv_area_copy(&blend_area, &rel_coords);
else if(!lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
return; /*Fully clipped, nothing to do*/
const uint8_t * src_buf = img_dsc->data;
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
int32_t src_stride = img_dsc->header.stride;
lv_color_format_t src_cf = img_dsc->header.cf;
uint8_t * dest_buf = draw_buf->data;
int32_t dest_stride = draw_buf->header.stride;
lv_color_format_t dest_cf = draw_buf->header.cf;
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
if(has_recolor && !has_transform)
_pxp_blit_recolor(dest_buf, &blend_area, dest_stride, dest_cf,
src_buf, &src_area, src_stride, src_cf, dsc);
else if(has_transform)
_pxp_blit_transform(dest_buf, &blend_area, dest_stride, dest_cf,
src_buf, &src_area, src_stride, src_cf, dsc);
else
_pxp_blit(dest_buf, &blend_area, dest_stride, dest_cf,
src_buf, &src_area, src_stride, src_cf, dsc->opa);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc)
{
int32_t dest_w = lv_area_get_width(dest_area);
int32_t dest_h = lv_area_get_height(dest_area);
int32_t src_w = lv_area_get_width(src_area);
int32_t src_h = lv_area_get_height(src_area);
bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888);
uint8_t src_px_size = lv_color_format_get_size(src_cf);
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
lv_pxp_reset();
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = pxp_get_as_px_format(src_cf),
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
.pitchBytes = src_stride
};
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
/*Disable PS, use as color generator*/
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->recolor));
/*Output buffer*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = pxp_get_out_px_format(dest_cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
/**
* Configure Porter-Duff blending.
*
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
* srcFactorMode is actually applied on PS alpha value
* dstFactorMode is actually applied on AS alpha value
*/
pxp_porter_duff_config_t pdConfig = {
.enable = 1,
.dstColorMode = kPXP_PorterDuffColorWithAlpha,
.srcColorMode = kPXP_PorterDuffColorWithAlpha,
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.srcGlobalAlphaMode = src_has_alpha ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
.dstFactorMode = kPXP_PorterDuffFactorStraight,
.srcFactorMode = kPXP_PorterDuffFactorInversed,
.dstGlobalAlpha = dsc->recolor_opa,
.srcGlobalAlpha = 0xff,
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
};
PXP_SetPorterDuffConfig(PXP_ID, &pdConfig);
lv_pxp_run();
}
static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc)
{
int32_t src_w = lv_area_get_width(src_area);
int32_t src_h = lv_area_get_height(src_area);
int32_t dest_w = lv_area_get_width(dest_area);
int32_t dest_h = lv_area_get_height(dest_area);
lv_point_t pivot = dsc->pivot;
/*The offsets are now relative to the transformation result with pivot ULC*/
int32_t piv_offset_x = 0;
int32_t piv_offset_y = 0;
int32_t trim_x = 0;
int32_t trim_y = 0;
bool has_rotation = (dsc->rotation != 0);
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
uint8_t src_px_size = lv_color_format_get_size(src_cf);
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
lv_pxp_reset();
if(has_rotation) {
/*Convert rotation angle and calculate offsets caused by pivot*/
pxp_rotate_degree_t pxp_angle;
switch(dsc->rotation) {
case 0:
pxp_angle = kPXP_Rotate0;
piv_offset_x = 0;
piv_offset_y = 0;
break;
case 900:
pxp_angle = kPXP_Rotate90;
piv_offset_x = pivot.x + pivot.y - src_h;
piv_offset_y = pivot.y - pivot.x;
break;
case 1800:
pxp_angle = kPXP_Rotate180;
piv_offset_x = 2 * pivot.x - src_w;
piv_offset_y = 2 * pivot.y - src_h;
break;
case 2700:
pxp_angle = kPXP_Rotate270;
piv_offset_x = pivot.x - pivot.y;
piv_offset_y = pivot.x + pivot.y - src_w;
break;
default:
pxp_angle = kPXP_Rotate0;
piv_offset_x = 0;
piv_offset_y = 0;
}
/*PS buffer rotation and decimation does not function at the same time*/
PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable);
}
if(has_scale) {
float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE;
float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE;
int32_t int_scale_x = (int32_t)fp_scale_x;
int32_t int_scale_y = (int32_t)fp_scale_y;
/*Any scale_factor in (k, k + 1] will result in a trim equal to k*/
trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x;
trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y;
dest_w = src_w * fp_scale_x + trim_x;
dest_h = src_h * fp_scale_y + trim_y;
/*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/
piv_offset_x = floorf(fp_scale_x * piv_offset_x) - floorf((fp_scale_x - 1) * pivot.x);
piv_offset_y = floorf(fp_scale_y * piv_offset_y) - floorf((fp_scale_y - 1) * pivot.y);
}
/*PS buffer - source image*/
pxp_ps_buffer_config_t psBufferConfig = {
.pixelFormat = pxp_get_ps_px_format(src_cf),
.swapByte = false,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
.bufferAddrU = 0,
.bufferAddrV = 0,
.pitchBytes = src_stride
};
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_x - 1U, dest_h - trim_y - 1U);
if(has_scale)
PXP_SetProcessSurfaceScaler(PXP_ID, src_w, src_h, dest_w, dest_h);
/*AS disabled */
PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
/*Output buffer*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = pxp_get_out_px_format(dest_cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * (dest_area->y1 + piv_offset_y) + dest_px_size * (dest_area->x1 + piv_offset_x)),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = dest_w - trim_x,
.height = dest_h - trim_y
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
lv_pxp_run();
}
static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
int32_t src_stride, lv_color_format_t src_cf, lv_opa_t opa)
{
int32_t dest_w = lv_area_get_width(dest_area);
int32_t dest_h = lv_area_get_height(dest_area);
int32_t src_w = lv_area_get_width(src_area);
int32_t src_h = lv_area_get_height(src_area);
bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888);
uint8_t src_px_size = lv_color_format_get_size(src_cf);
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
lv_pxp_reset();
pxp_as_blend_config_t asBlendConfig = {
.alpha = opa,
.invertAlpha = false,
.alphaMode = kPXP_AlphaRop,
.ropMode = kPXP_RopMergeAs
};
if(opa >= (lv_opa_t)LV_OPA_MAX && !src_has_alpha) {
/*Simple blit, no effect - Disable PS buffer*/
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
}
else {
/*PS must be enabled to fetch background pixels.
PS and OUT buffers are the same, blend will be done in-place*/
pxp_ps_buffer_config_t psBufferConfig = {
.pixelFormat = pxp_get_ps_px_format(dest_cf),
.swapByte = false,
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
.bufferAddrU = 0U,
.bufferAddrV = 0U,
.pitchBytes = dest_stride
};
if(opa >= (lv_opa_t)LV_OPA_MAX)
asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaEmbedded : kPXP_AlphaOverride;
else
asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = pxp_get_as_px_format(src_cf),
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
.pitchBytes = src_stride
};
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
PXP_SetAlphaSurfaceBlendConfig(PXP_ID, &asBlendConfig);
PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false);
/*Output buffer.*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = pxp_get_out_px_format(dest_cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
lv_pxp_run();
}
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,158 +0,0 @@
/**
* @file lv_draw_pxp_layer.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP
#include "../../../stdlib/lv_string.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords)
{
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
const lv_draw_buf_t * draw_buf = layer_to_draw->draw_buf;
/* It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
* In this case just return.
*/
if(draw_buf == NULL)
return;
const lv_area_t area_to_draw = {
.x1 = 0,
.y1 = 0,
.x2 = draw_buf->header.w - 1,
.y2 = draw_buf->header.h - 1
};
lv_draw_buf_invalidate_cache(draw_buf, &area_to_draw);
lv_draw_image_dsc_t new_draw_dsc = *draw_dsc;
new_draw_dsc.src = draw_buf;
lv_draw_pxp_img(draw_unit, &new_draw_dsc, coords);
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
lv_area_t area_rot;
lv_area_copy(&area_rot, coords);
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
int32_t w = lv_area_get_width(coords);
int32_t h = lv_area_get_height(coords);
lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
&draw_dsc->pivot);
area_rot.x1 += coords->x1;
area_rot.y1 += coords->y1;
area_rot.x2 += coords->x1;
area_rot.y2 += coords->y1;
}
lv_area_t draw_area;
if(!lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
#endif
#if LV_USE_LAYER_DEBUG
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
fill_dsc.opa = LV_OPA_20;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = fill_dsc.color;
border_dsc.opa = LV_OPA_60;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
#endif
#if LV_USE_PARALLEL_DRAW_DEBUG
uint32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != draw_unit) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_fill_dsc_t fill_dsc;
lv_draw_rect_dsc_init(&fill_dsc);
fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
fill_dsc.opa = LV_OPA_10;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
border_dsc.opa = LV_OPA_100;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y2;
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_black();
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_white();
label_dsc.text = buf;
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
#endif
}
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,93 +0,0 @@
/**
* @file lv_pxp_cfg.c
*
*/
/**
* Copyright 2020-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_pxp_cfg.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "lv_pxp_osa.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static pxp_cfg_t * _pxp_cfg;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_pxp_init(void)
{
_pxp_cfg = pxp_get_default_cfg();
PXP_Init(PXP_ID);
PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
_pxp_cfg->pxp_interrupt_init();
}
void lv_pxp_deinit(void)
{
_pxp_cfg->pxp_interrupt_deinit();
PXP_DisableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
PXP_Deinit(PXP_ID);
}
void lv_pxp_reset(void)
{
PXP_ResetControl(PXP_ID);
PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
}
void lv_pxp_run(void)
{
_pxp_cfg->pxp_run();
_pxp_cfg->pxp_wait();
}
void lv_pxp_wait(void)
{
_pxp_cfg->pxp_wait();
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,104 +0,0 @@
/**
* @file lv_pxp_cfg.h
*
*/
/**
* Copyright 2020-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_PXP_CFG_H
#define LV_PXP_CFG_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "fsl_cache.h"
#include "fsl_pxp.h"
#include "../../../misc/lv_log.h"
/*********************
* DEFINES
*********************/
/** PXP module instance to use*/
#define PXP_ID PXP
/** PXP interrupt line ID*/
#define PXP_IRQ_ID PXP_IRQn
/**********************
* TYPEDEFS
**********************/
/**
* NXP PXP device configuration.
*/
typedef struct {
/** Callback for PXP interrupt initialization*/
void (*pxp_interrupt_init)(void);
/** Callback for PXP interrupt de-initialization*/
void (*pxp_interrupt_deinit)(void);
/** Callback for PXP start*/
void (*pxp_run)(void);
/** Callback for waiting of PXP completion*/
void (*pxp_wait)(void);
} pxp_cfg_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Reset and initialize PXP device. This function should be called as a part
* of display init sequence.
*/
void lv_pxp_init(void);
/**
* Disable PXP device. Should be called during display deinit sequence.
*/
void lv_pxp_deinit(void);
/**
* Reset PXP device.
*/
void lv_pxp_reset(void);
/**
* Clear cache and start PXP.
*/
void lv_pxp_run(void);
/**
* Wait for PXP completion.
*/
void lv_pxp_wait(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PXP_CFG_H*/

View File

@@ -1,188 +0,0 @@
/**
* @file lv_pxp_osa.c
*
*/
/**
* Copyright 2020, 2022-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_pxp_osa.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "lv_pxp_utils.h"
#include "../../../misc/lv_log.h"
#include "../../../osal/lv_os.h"
#include "fsl_pxp.h"
#if defined(SDK_OS_FREE_RTOS)
#include "FreeRTOS.h"
#endif
#if defined(__ZEPHYR__)
#include <zephyr/kernel.h>
#include <zephyr/irq.h>
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* PXP interrupt initialization.
*/
static void _pxp_interrupt_init(void);
/**
* PXP interrupt de-initialization.
*/
static void _pxp_interrupt_deinit(void);
/**
* Start the PXP job.
*/
static void _pxp_run(void);
/**
* Wait for PXP completion.
*/
static void _pxp_wait(void);
#if defined(__ZEPHYR__)
/**
* Interrupt handler for Zephyr IRQ
*/
static void _pxp_zephyr_irq_handler(void *);
#endif
/**********************
* STATIC VARIABLES
**********************/
#if LV_USE_OS
static lv_thread_sync_t pxp_sync;
#endif
static volatile bool ucPXPIdle;
static pxp_cfg_t _pxp_default_cfg = {
.pxp_interrupt_init = _pxp_interrupt_init,
.pxp_interrupt_deinit = _pxp_interrupt_deinit,
.pxp_run = _pxp_run,
.pxp_wait = _pxp_wait,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void PXP_IRQHandler(void)
{
if(kPXP_CompleteFlag & PXP_GetStatusFlags(PXP_ID)) {
PXP_ClearStatusFlags(PXP_ID, kPXP_CompleteFlag);
#if LV_USE_OS
lv_thread_sync_signal_isr(&pxp_sync);
#else
ucPXPIdle = true;
#endif
}
}
pxp_cfg_t * pxp_get_default_cfg(void)
{
return &_pxp_default_cfg;
}
/**********************
* STATIC FUNCTIONS
**********************/
#if defined(__ZEPHYR__)
static void _pxp_zephyr_irq_handler(void *)
{
PXP_IRQHandler();
}
#endif
static void _pxp_interrupt_init(void)
{
#if LV_USE_OS
if(lv_thread_sync_init(&pxp_sync) != LV_RESULT_OK) {
PXP_ASSERT_MSG(false, "Failed to init thread_sync.");
}
#endif
#if defined(__ZEPHYR__)
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(pxp)), CONFIG_LV_Z_PXP_INTERRUPT_PRIORITY, _pxp_zephyr_irq_handler, NULL, 0);
irq_enable(DT_IRQN(DT_NODELABEL(pxp)));
#elif defined(SDK_OS_FREE_RTOS)
NVIC_SetPriority(PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
#endif
#if !defined(__ZEPHYR__)
NVIC_EnableIRQ(PXP_IRQ_ID);
#endif
ucPXPIdle = true;
}
static void _pxp_interrupt_deinit(void)
{
#if defined(__ZEPHYR__)
irq_disable(DT_IRQN(DT_NODELABEL(pxp)));
#else
NVIC_DisableIRQ(PXP_IRQ_ID);
#endif
#if LV_USE_OS
lv_thread_sync_delete(&pxp_sync);
#endif
}
/**
* Function to start PXP job.
*/
static void _pxp_run(void)
{
ucPXPIdle = false;
PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
PXP_Start(PXP_ID);
}
/**
* Function to wait for PXP completion.
*/
static void _pxp_wait(void)
{
if(ucPXPIdle == true)
return;
#if LV_USE_OS
if(lv_thread_sync_wait(&pxp_sync) == LV_RESULT_OK)
ucPXPIdle = true;
#else
while(ucPXPIdle == false) {
}
#endif
}
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,62 +0,0 @@
/**
* @file lv_pxp_osa.h
*
*/
/**
* Copyright 2020, 2022-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_PXP_OSA_H
#define LV_PXP_OSA_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "lv_pxp_cfg.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* PXP device interrupt handler. Used to check PXP task completion status.
*/
void PXP_IRQHandler(void);
/**
* Get the PXP default configuration.
*/
pxp_cfg_t * pxp_get_default_cfg(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PXP_OSA_H*/

View File

@@ -1,149 +0,0 @@
/**
* @file lv_pxp_utils.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_pxp_utils.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf)
{
pxp_output_pixel_format_t out_px_format = kPXP_OutputPixelFormatRGB565;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
out_px_format = kPXP_OutputPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB888:
out_px_format = kPXP_OutputPixelFormatRGB888P;
break;
case LV_COLOR_FORMAT_ARGB8888:
out_px_format = kPXP_OutputPixelFormatARGB8888;
break;
case LV_COLOR_FORMAT_XRGB8888:
out_px_format = kPXP_OutputPixelFormatRGB888;
break;
default:
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return out_px_format;
}
pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf)
{
pxp_as_pixel_format_t as_px_format = kPXP_AsPixelFormatRGB565;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
as_px_format = kPXP_AsPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB888:
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
case LV_COLOR_FORMAT_ARGB8888:
as_px_format = kPXP_AsPixelFormatARGB8888;
break;
case LV_COLOR_FORMAT_XRGB8888:
as_px_format = kPXP_AsPixelFormatRGB888;
break;
default:
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return as_px_format;
}
#if LV_USE_DRAW_PXP
pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf)
{
pxp_ps_pixel_format_t ps_px_format = kPXP_PsPixelFormatRGB565;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
ps_px_format = kPXP_PsPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB888:
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
case LV_COLOR_FORMAT_ARGB8888:
#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \
(!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3))
ps_px_format = kPXP_PsPixelFormatARGB8888;
#else
PXP_ASSERT_MSG(false, "Unsupported color format.");
#endif
break;
case LV_COLOR_FORMAT_XRGB8888:
#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \
(!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3))
ps_px_format = kPXP_PsPixelFormatARGB8888;
#else
ps_px_format = kPXP_PsPixelFormatRGB888;
#endif
break;
default:
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return ps_px_format;
}
bool pxp_buf_aligned(const void * buf, uint32_t stride)
{
/* Test for pointer alignment */
if((uintptr_t)buf % 64)
return false;
/* Test for invalid stride (no stride alignment required) */
if(stride == 0)
return false;
return true;
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/

View File

@@ -1,84 +0,0 @@
/**
* @file lv_pxp_utils.h
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_PXP_UTILS_H
#define LV_PXP_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PXP
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
#include "fsl_pxp.h"
#include "../../../misc/lv_color.h"
/*********************
* DEFINES
*********************/
#if LV_USE_PXP_ASSERT
#define PXP_ASSERT(expr) LV_ASSERT(expr)
#else
#define PXP_ASSERT(expr)
#endif
#define PXP_ASSERT_MSG(expr, msg) \
do { \
if(!(expr)) { \
LV_LOG_ERROR(msg); \
PXP_ASSERT(false); \
} \
} while(0)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf);
pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf);
#if LV_USE_DRAW_PXP
pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf);
bool pxp_buf_aligned(const void * buf, uint32_t stride);
/**********************
* MACROS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_PXP*/
#endif /*LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP*/
#endif /*LV_USE_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PXP_UTILS_H*/

View File

@@ -1,131 +0,0 @@
/**
* @file lv_draw_buf_vglite.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "../../lv_draw_buf_private.h"
#include "lv_vglite_buf.h"
#include "lv_vglite_utils.h"
#include "lvgl_support.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_buf_vglite_init_handlers(void)
{
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
lv_draw_buf_handlers_t * font_handlers = lv_draw_buf_get_font_handlers();
lv_draw_buf_handlers_t * image_handlers = lv_draw_buf_get_image_handlers();
handlers->invalidate_cache_cb = _invalidate_cache;
font_handlers->invalidate_cache_cb = _invalidate_cache;
image_handlers->invalidate_cache_cb = _invalidate_cache;
handlers->width_to_stride_cb = _width_to_stride;
font_handlers->width_to_stride_cb = _width_to_stride;
image_handlers->width_to_stride_cb = _width_to_stride;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
const lv_image_header_t * header = &draw_buf->header;
uint32_t stride = header->stride;
lv_color_format_t cf = header->cf;
if(area->y1 == 0) {
uint32_t size = stride * lv_area_get_height(area);
/* Invalidate full buffer. */
DEMO_CleanInvalidateCacheByAddr((void *)draw_buf->data, size);
return;
}
const uint8_t * buf_u8 = draw_buf->data;
/* ARM require a 32 byte aligned address. */
uint8_t align_bytes = 32;
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
uint16_t offset_x = 0;
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
offset_x = area->x1 - shift_x;
buf_u8 += (shift_x * bits_per_pixel) / 8;
}
if(area->y1) {
uint16_t shift_y = area->y1;
buf_u8 += shift_y * stride;
}
/* Area to clear can start from a different offset in buffer.
* Invalidate the area line by line.
*/
uint16_t line_pixels = offset_x + lv_area_get_width(area);
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
uint16_t area_height = lv_area_get_height(area);
for(uint16_t y = 0; y < area_height; y++) {
const void * line_addr = buf_u8 + y * stride;
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
}
}
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
{
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint32_t width_bits = (w * bits_per_pixel + 7) & ~7;
uint32_t width_bytes = width_bits / 8;
uint8_t align_bytes = vglite_get_stride_alignment(cf);
return (width_bytes + align_bytes - 1) & ~(align_bytes - 1);
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,594 +0,0 @@
/**
* @file lv_draw_vglite.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_utils.h"
#include "../../../core/lv_global.h"
/*********************
* DEFINES
*********************/
#define DRAW_UNIT_ID_VGLITE 2
#if LV_USE_VGLITE_DRAW_ASYNC
#define VGLITE_TASK_BUF_SIZE 100
#endif
/**********************
* TYPEDEFS
**********************/
#if LV_USE_VGLITE_DRAW_ASYNC
/**
* Structure of pending vglite draw task
*/
typedef struct _vglite_draw_task_t {
lv_draw_task_t * task;
bool flushed;
} vglite_draw_tasks_t;
#endif
/**********************
* STATIC PROTOTYPES
**********************/
/*
* Evaluate a task and set the score and preferred VGLite draw unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
*/
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/*
* Dispatch (assign) a task to VGLite draw unit (itself).
* Return 1 if task was dispatched, 0 otherwise (task not supported).
*/
static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/*
* Wait for VG-Lite draw unit to finish.
*/
#if LV_USE_VGLITE_DRAW_ASYNC
static int32_t _vglite_wait_for_finish(lv_draw_unit_t * draw_unit);
#endif
/*
* Delete the VGLite draw unit.
*/
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit);
#if LV_USE_VGLITE_DRAW_THREAD
static void _vglite_render_thread_cb(void * ptr);
#endif
static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u);
/**********************
* STATIC VARIABLES
**********************/
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#if LV_USE_VGLITE_DRAW_ASYNC
/*
* Circular buffer to hold the queued and the flushed tasks.
* Two indexes, _head and _tail, are used to signal the beginning
* and the end of the valid tasks that are pending.
*/
static vglite_draw_tasks_t _draw_task_buf[VGLITE_TASK_BUF_SIZE];
static volatile int _head = 0;
static volatile int _tail = 0;
#endif
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_init(void)
{
lv_draw_buf_vglite_init_handlers();
lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
#if LV_USE_VGLITE_DRAW_ASYNC
draw_vglite_unit->base_unit.wait_for_finish_cb = _vglite_wait_for_finish;
#endif
draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
#if LV_USE_VGLITE_DRAW_THREAD
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
#endif
}
void lv_draw_vglite_deinit(void)
{
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline bool _vglite_src_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
#if CHIPID == 0x255 || CHIPID == 0x555
case LV_COLOR_FORMAT_I1:
case LV_COLOR_FORMAT_I2:
case LV_COLOR_FORMAT_I4:
case LV_COLOR_FORMAT_I8:
#endif
case LV_COLOR_FORMAT_A4:
case LV_COLOR_FORMAT_A8:
case LV_COLOR_FORMAT_L8:
case LV_COLOR_FORMAT_RGB565:
#if CHIPID == 0x555
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_RGB888:
#endif
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static inline bool _vglite_dest_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_A8:
#if CHIPID == 0x255 || CHIPID == 0x555
case LV_COLOR_FORMAT_L8:
#endif
case LV_COLOR_FORMAT_RGB565:
#if CHIPID == 0x555
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_RGB888:
#endif
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
{
LV_UNUSED(u);
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
if(!_vglite_dest_cf_supported(draw_dsc_base->layer->color_format))
return 0;
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL:
if(t->preference_score > 80) {
t->preference_score = 80;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
case LV_DRAW_TASK_TYPE_LINE:
case LV_DRAW_TASK_TYPE_ARC:
case LV_DRAW_TASK_TYPE_TRIANGLE:
if(t->preference_score > 90) {
t->preference_score = 90;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
case LV_DRAW_TASK_TYPE_LABEL:
if(t->preference_score > 95) {
t->preference_score = 95;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
case LV_DRAW_TASK_TYPE_BORDER: {
if(t->preference_score > 90) {
t->preference_score = 90;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
}
case LV_DRAW_TASK_TYPE_LAYER: {
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
#if LV_USE_VGLITE_BLIT_SPLIT
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
#endif
if(!_vglite_src_cf_supported(layer_to_draw->color_format)
#if LV_USE_VGLITE_BLIT_SPLIT
|| has_transform
#endif
)
return 0;
if(t->preference_score > 80) {
t->preference_score = 80;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
}
case LV_DRAW_TASK_TYPE_IMAGE: {
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
const lv_image_dsc_t * img_dsc = draw_dsc->src;
#if LV_USE_VGLITE_BLIT_SPLIT
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
#endif
if((!_vglite_src_cf_supported(img_dsc->header.cf))
#if LV_USE_VGLITE_BLIT_SPLIT
|| has_transform
#endif
|| (!vglite_src_buf_aligned(img_dsc->data, img_dsc->header.stride, img_dsc->header.cf))
)
return 0;
if(t->preference_score > 80) {
t->preference_score = 80;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
}
default:
return 0;
}
return 0;
}
static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
/* Return immediately if it's busy with draw task. */
if(draw_vglite_unit->task_act)
return 0;
/* Try to get an ready to draw. */
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE);
if(t == NULL)
return LV_DRAW_UNIT_IDLE;
if(t->preferred_draw_unit_id != DRAW_UNIT_ID_VGLITE) {
/* Let the preferred known unit to draw this task. */
if(t->preferred_draw_unit_id != LV_DRAW_UNIT_NONE) {
return LV_DRAW_UNIT_IDLE;
}
else {
/* Fake unsupported tasks as ready. */
t->state = LV_DRAW_TASK_STATE_READY;
/* Request a new dispatching as it can get a new task. */
lv_draw_dispatch_request();
return 1;
}
}
if(lv_draw_layer_alloc_buf(layer) == NULL)
return LV_DRAW_UNIT_IDLE;
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
draw_vglite_unit->base_unit.target_layer = layer;
draw_vglite_unit->base_unit.clip_area = &t->clip_area;
draw_vglite_unit->task_act = t;
#if LV_USE_VGLITE_DRAW_THREAD
/* Let the render thread work. */
if(draw_vglite_unit->inited)
lv_thread_sync_signal(&draw_vglite_unit->sync);
#else
_vglite_execute_drawing(draw_vglite_unit);
draw_vglite_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
draw_vglite_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();
#endif
return 1;
}
#if LV_USE_VGLITE_DRAW_ASYNC
static int32_t _vglite_wait_for_finish(lv_draw_unit_t * draw_unit)
{
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
draw_vglite_unit->wait_for_finish = true;
/* Signal draw unit to finish its tasks and return READY state after completion. */
if(draw_vglite_unit->inited)
lv_thread_sync_signal(&draw_vglite_unit->sync);
/* Wait for finish now. */
lv_draw_dispatch_wait_for_request();
return 1;
}
#endif
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit)
{
#if LV_USE_VGLITE_DRAW_THREAD
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
LV_LOG_INFO("Cancel VGLite draw thread.");
draw_vglite_unit->exit_status = true;
if(draw_vglite_unit->inited)
lv_thread_sync_signal(&draw_vglite_unit->sync);
lv_result_t res = lv_thread_delete(&draw_vglite_unit->thread);
return res;
#else
LV_UNUSED(draw_unit);
return 1;
#endif
}
static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
lv_layer_t * layer = draw_unit->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
/* Set target buffer */
vglite_set_dest_buf(draw_buf->data, draw_buf->header.w, draw_buf->header.h, draw_buf->header.stride,
draw_buf->header.cf);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t draw_area;
lv_area_copy(&draw_area, &t->area);
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
if(!lv_area_intersect(&draw_area, &draw_area, &clip_area))
return; /*Fully clipped, nothing to do*/
if(_draw_info.unit_cnt > 1)
lv_draw_buf_invalidate_cache(draw_buf, &draw_area);
/* Set scissor area, excluding the split blit case */
#if LV_USE_VGLITE_BLIT_SPLIT
if(t->type != LV_DRAW_TASK_TYPE_IMAGE || t->type != LV_DRAW_TASK_TYPE_LAYER)
#endif
vglite_set_scissor(&clip_area);
switch(t->type) {
case LV_DRAW_TASK_TYPE_LABEL:
lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_FILL:
lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_BORDER:
lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_ARC:
lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_LINE:
lv_draw_vglite_line(draw_unit, t->draw_dsc);
break;
case LV_DRAW_TASK_TYPE_LAYER:
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_TRIANGLE:
lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
break;
default:
break;
}
/* Disable scissor */
vglite_set_scissor(&layer->buf_area);
#if LV_USE_PARALLEL_DRAW_DEBUG
/*Layers manage it for themselves*/
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
lv_area_t draw_area;
if(!lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
return;
int32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_palette_main(idx % LV_PALETTE_LAST);
rect_dsc.border_color = rect_dsc.bg_color;
rect_dsc.bg_opa = LV_OPA_10;
rect_dsc.border_opa = LV_OPA_80;
rect_dsc.border_width = 1;
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.y1 = draw_area.y1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y1 + txt_size.y - 1;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_color_white();
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_black();
label_dsc.text = buf;
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
}
#endif
}
#if LV_USE_VGLITE_DRAW_ASYNC
static inline void _vglite_queue_task(lv_draw_task_t * task)
{
VGLITE_ASSERT_MSG(((_tail + 1) % VGLITE_TASK_BUF_SIZE) != _head, "VGLite task buffer full.");
_draw_task_buf[_tail].task = task;
_draw_task_buf[_tail].flushed = false;
_tail = (_tail + 1) % VGLITE_TASK_BUF_SIZE;
}
static inline void _vglite_signal_task_ready(lv_draw_task_t * task)
{
/* Signal the ready state to dispatcher. */
task->state = LV_DRAW_TASK_STATE_READY;
_head = (_head + 1) % VGLITE_TASK_BUF_SIZE;
/* No need to cleanup the tasks in buffer as we advance with the _head. */
}
static inline void _vglite_signal_all_task_ready(void)
{
int end = (_head <= _tail) ? _tail : _tail + VGLITE_TASK_BUF_SIZE;
for(int i = _head; i < end; i++) {
lv_draw_task_t * task = _draw_task_buf[i % VGLITE_TASK_BUF_SIZE].task;
_vglite_signal_task_ready(task);
}
}
static inline void _vglite_signal_flushed_task_ready(void)
{
if(vglite_cmd_buf_is_flushed()) {
int end = (_head <= _tail) ? _tail : _tail + VGLITE_TASK_BUF_SIZE;
for(int i = _head; i < end; i++) {
if(_draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed) {
lv_draw_task_t * task = _draw_task_buf[i % VGLITE_TASK_BUF_SIZE].task;
_vglite_signal_task_ready(task);
}
else {
/* Those tasks have been flushed now. */
_draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed = true;
}
}
}
}
#endif
#if LV_USE_VGLITE_DRAW_THREAD
static void _vglite_render_thread_cb(void * ptr)
{
lv_draw_vglite_unit_t * u = ptr;
lv_thread_sync_init(&u->sync);
u->inited = true;
while(1) {
/* Wait for sync if there is no task set. */
while(u->task_act == NULL
#if LV_USE_VGLITE_DRAW_ASYNC
/*
* Wait for sync if _draw_task_buf is empty.
* The thread will have to run to complete any pending tasks.
*/
&& !u->wait_for_finish
#endif
) {
if(u->exit_status)
break;
lv_thread_sync_wait(&u->sync);
}
if(u->exit_status) {
LV_LOG_INFO("Ready to exit VGLite draw thread.");
break;
}
if(u->task_act) {
#if LV_USE_VGLITE_DRAW_ASYNC
_vglite_queue_task((void *)u->task_act);
#endif
_vglite_execute_drawing(u);
}
#if LV_USE_VGLITE_DRAW_ASYNC
if(u->wait_for_finish) {
u->wait_for_finish = false;
vglite_wait_for_finish();
_vglite_signal_all_task_ready();
}
else { /* u->task_act */
_vglite_signal_flushed_task_ready();
}
#else
/* Signal the ready state to dispatcher. */
u->task_act->state = LV_DRAW_TASK_STATE_READY;
#endif
/* Cleanup. */
u->task_act = NULL;
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
lv_draw_dispatch_request();
}
u->inited = false;
lv_thread_sync_delete(&u->sync);
LV_LOG_INFO("Exit VGLite draw thread.");
}
#endif
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,86 +0,0 @@
/**
* @file lv_draw_vglite.h
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_DRAW_VGLITE_H
#define LV_DRAW_VGLITE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_VGLITE
#include "../../lv_draw_private.h"
#include "../../sw/lv_draw_sw_private.h"
#include "../../../misc/lv_area_private.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct lv_draw_vglite_unit {
lv_draw_sw_unit_t;
#if LV_USE_VGLITE_DRAW_ASYNC
volatile bool wait_for_finish;
#endif
} lv_draw_vglite_unit_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_buf_vglite_init_handlers(void);
void lv_draw_vglite_init(void);
void lv_draw_vglite_deinit(void);
void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords);
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_VGLITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_H*/

View File

@@ -1,686 +0,0 @@
/**
* @file lv_draw_vglite_arc.c
*
*/
/**
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_path.h"
#include "lv_vglite_utils.h"
#include "../../../stdlib/lv_string.h"
#include <math.h>
/*********************
* DEFINES
*********************/
#define T_FRACTION 16384.0f
#define DICHOTO_ITER 5
static const uint16_t TperDegree[90] = {
0, 174, 348, 522, 697, 873, 1049, 1226, 1403, 1581,
1759, 1938, 2117, 2297, 2477, 2658, 2839, 3020, 3202, 3384,
3567, 3749, 3933, 4116, 4300, 4484, 4668, 4852, 5037, 5222,
5407, 5592, 5777, 5962, 6148, 6334, 6519, 6705, 6891, 7077,
7264, 7450, 7636, 7822, 8008, 8193, 8378, 8564, 8750, 8936,
9122, 9309, 9495, 9681, 9867, 10052, 10238, 10424, 10609, 10794,
10979, 11164, 11349, 11534, 11718, 11902, 12086, 12270, 12453, 12637,
12819, 13002, 13184, 13366, 13547, 13728, 13909, 14089, 14269, 14448,
14627, 14805, 14983, 15160, 15337, 15513, 15689, 15864, 16038, 16212
};
/**********************
* TYPEDEFS
**********************/
/* intermediate arc params */
typedef struct _vg_arc {
int32_t angle; /* angle <90deg */
int32_t quarter; /* 0-3 counter-clockwise */
int32_t rad; /* radius */
int32_t p0x; /* point P0 */
int32_t p0y;
int32_t p1x; /* point P1 */
int32_t p1y;
int32_t p2x; /* point P2 */
int32_t p2y;
int32_t p3x; /* point P3 */
int32_t p3y;
} vg_arc;
typedef struct _cubic_cont_pt {
float p0;
float p1;
float p2;
float p3;
} cubic_cont_pt;
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Draw arc shape with effects
*
* @param[in] center Arc center with relative coordinates
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
*
*/
static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area,
const lv_draw_arc_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
const lv_area_t * coords)
{
LV_UNUSED(coords);
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(dsc->width == 0)
return;
if(dsc->start_angle == dsc->end_angle)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_point_t center = {dsc->center.x - layer->buf_area.x1, dsc->center.y - layer->buf_area.y1};
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
_vglite_draw_arc(&center, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _copy_arc(vg_arc * dst, vg_arc * src)
{
dst->quarter = src->quarter;
dst->rad = src->rad;
dst->angle = src->angle;
dst->p0x = src->p0x;
dst->p1x = src->p1x;
dst->p2x = src->p2x;
dst->p3x = src->p3x;
dst->p0y = src->p0y;
dst->p1y = src->p1y;
dst->p2y = src->p2y;
dst->p3y = src->p3y;
}
/**
* Rotate the point according given rotation angle rotation center is 0,0
*/
static void _rotate_point(int32_t angle, int32_t * x, int32_t * y)
{
int32_t ori_x = *x;
int32_t ori_y = *y;
int16_t alpha = (int16_t)angle;
*x = ((lv_trigo_cos(alpha) * ori_x) / LV_TRIGO_SIN_MAX) - ((lv_trigo_sin(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
*y = ((lv_trigo_sin(alpha) * ori_x) / LV_TRIGO_SIN_MAX) + ((lv_trigo_cos(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
}
/**
* Set full arc control points depending on quarter.
* Control points match the best approximation of a circle.
* Arc Quarter position is:
* Q2 | Q3
* ---+---
* Q1 | Q0
*/
static void _set_full_arc(vg_arc * fullarc)
{
/* the tangent length for the bezier circle approx */
float tang = ((float)fullarc->rad) * BEZIER_OPTIM_CIRCLE;
switch(fullarc->quarter) {
case 0:
/* first quarter */
fullarc->p0x = fullarc->rad;
fullarc->p0y = 0;
fullarc->p1x = fullarc->rad;
fullarc->p1y = (int32_t)tang;
fullarc->p2x = (int32_t)tang;
fullarc->p2y = fullarc->rad;
fullarc->p3x = 0;
fullarc->p3y = fullarc->rad;
break;
case 1:
/* second quarter */
fullarc->p0x = 0;
fullarc->p0y = fullarc->rad;
fullarc->p1x = 0 - (int32_t)tang;
fullarc->p1y = fullarc->rad;
fullarc->p2x = 0 - fullarc->rad;
fullarc->p2y = (int32_t)tang;
fullarc->p3x = 0 - fullarc->rad;
fullarc->p3y = 0;
break;
case 2:
/* third quarter */
fullarc->p0x = 0 - fullarc->rad;
fullarc->p0y = 0;
fullarc->p1x = 0 - fullarc->rad;
fullarc->p1y = 0 - (int32_t)tang;
fullarc->p2x = 0 - (int32_t)tang;
fullarc->p2y = 0 - fullarc->rad;
fullarc->p3x = 0;
fullarc->p3y = 0 - fullarc->rad;
break;
case 3:
/* fourth quarter */
fullarc->p0x = 0;
fullarc->p0y = 0 - fullarc->rad;
fullarc->p1x = (int32_t)tang;
fullarc->p1y = 0 - fullarc->rad;
fullarc->p2x = fullarc->rad;
fullarc->p2y = 0 - (int32_t)tang;
fullarc->p3x = fullarc->rad;
fullarc->p3y = 0;
break;
default:
VGLITE_ASSERT_MSG(false, "Invalid arc quarter.");
break;
}
}
/**
* Linear interpolation between two points 'a' and 'b'
* 't' parameter is the proportion ratio expressed in range [0 ; T_FRACTION ]
*/
static inline float _lerp(float coord_a, float coord_b, uint16_t t)
{
float tf = (float)t;
return ((T_FRACTION - tf) * coord_a + tf * coord_b) / T_FRACTION;
}
/**
* Computes a point of bezier curve given 't' param
*/
static inline float _comp_bezier_point(float t, cubic_cont_pt cp)
{
float t_sq = t * t;
float inv_t_sq = (1.0f - t) * (1.0f - t);
float apt = (1.0f - t) * inv_t_sq * cp.p0 + 3.0f * inv_t_sq * t * cp.p1 + 3.0f * (1.0f - t) * t_sq * cp.p2 + t * t_sq *
cp.p3;
return apt;
}
/**
* Find parameter 't' in curve at point 'pt'
* proceed by dichotomy on only 1 dimension,
* works only if the curve is monotonic
* bezier curve is defined by control points [p0 p1 p2 p3]
* 'dec' tells if curve is decreasing (true) or increasing (false)
*/
static uint16_t _get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec)
{
/* initialize dichotomy with boundary 't' values */
float t_low = 0.0f;
float t_mid = 0.5f;
float t_hig = 1.0f;
float a_pt;
/* dichotomy loop */
for(int i = 0; i < DICHOTO_ITER; i++) {
a_pt = _comp_bezier_point(t_mid, cp);
/* check mid-point position on bezier curve versus targeted point */
if((a_pt > pt) != dec) {
t_hig = t_mid;
}
else {
t_low = t_mid;
}
/* define new 't' param for mid-point */
t_mid = (t_low + t_hig) / 2.0f;
}
/* return parameter 't' in integer range [0 ; T_FRACTION] */
return (uint16_t)floorf(t_mid * T_FRACTION + 0.5f);
}
/**
* Gives relative coords of the control points
* for the sub-arc starting at angle with given angle span
*/
static void _get_subarc_control_points(vg_arc * arc, int32_t span)
{
vg_arc fullarc = {0};
fullarc.angle = arc->angle;
fullarc.quarter = arc->quarter;
fullarc.rad = arc->rad;
_set_full_arc(&fullarc);
/* special case of full arc */
if(arc->angle == 90) {
_copy_arc(arc, &fullarc);
return;
}
/* compute 1st arc using the geometric construction of curve */
uint16_t t2 = TperDegree[arc->angle + span];
/* lerp for A */
float a2x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t2);
float a2y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t2);
/* lerp for B */
float b2x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t2);
float b2y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t2);
/* lerp for C */
float c2x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t2);
float c2y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t2);
/* lerp for D */
float d2x = _lerp(a2x, b2x, t2);
float d2y = _lerp(a2y, b2y, t2);
/* lerp for E */
float e2x = _lerp(b2x, c2x, t2);
float e2y = _lerp(b2y, c2y, t2);
float pt2x = _lerp(d2x, e2x, t2);
float pt2y = _lerp(d2y, e2y, t2);
/* compute sub-arc using the geometric construction of curve */
uint16_t t1 = TperDegree[arc->angle];
/* lerp for A */
float a1x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t1);
float a1y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t1);
/* lerp for B */
float b1x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t1);
float b1y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t1);
/* lerp for C */
float c1x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t1);
float c1y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t1);
/* lerp for D */
float d1x = _lerp(a1x, b1x, t1);
float d1y = _lerp(a1y, b1y, t1);
/* lerp for E */
float e1x = _lerp(b1x, c1x, t1);
float e1y = _lerp(b1y, c1y, t1);
float pt1x = _lerp(d1x, e1x, t1);
float pt1y = _lerp(d1y, e1y, t1);
/* find the 't3' parameter for point P(t1) on the sub-arc [P0 A2 D2 P(t2)] using dichotomy
* use position of x axis only */
uint16_t t3;
t3 = _get_bez_t_from_pos(pt1x,
(cubic_cont_pt) {
.p0 = ((float)fullarc.p0x), .p1 = a2x, .p2 = d2x, .p3 = pt2x
},
(bool)(pt2x < (float)fullarc.p0x));
/* lerp for B */
float b3x = _lerp(a2x, d2x, t3);
float b3y = _lerp(a2y, d2y, t3);
/* lerp for C */
float c3x = _lerp(d2x, pt2x, t3);
float c3y = _lerp(d2y, pt2y, t3);
/* lerp for E */
float e3x = _lerp(b3x, c3x, t3);
float e3y = _lerp(b3y, c3y, t3);
arc->p0x = (int32_t)floorf(0.5f + pt1x);
arc->p0y = (int32_t)floorf(0.5f + pt1y);
arc->p1x = (int32_t)floorf(0.5f + e3x);
arc->p1y = (int32_t)floorf(0.5f + e3y);
arc->p2x = (int32_t)floorf(0.5f + c3x);
arc->p2y = (int32_t)floorf(0.5f + c3y);
arc->p3x = (int32_t)floorf(0.5f + pt2x);
arc->p3y = (int32_t)floorf(0.5f + pt2y);
}
/**
* Gives relative coords of the control points
*/
static void _get_arc_control_points(vg_arc * arc, bool start)
{
vg_arc fullarc = {0};
fullarc.angle = arc->angle;
fullarc.quarter = arc->quarter;
fullarc.rad = arc->rad;
_set_full_arc(&fullarc);
/* special case of full arc */
if(arc->angle == 90) {
_copy_arc(arc, &fullarc);
return;
}
/* compute sub-arc using the geometric construction of curve */
uint16_t t = TperDegree[arc->angle];
/* lerp for A */
float ax = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t);
float ay = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t);
/* lerp for B */
float bx = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t);
float by = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t);
/* lerp for C */
float cx = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t);
float cy = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t);
/* lerp for D */
float dx = _lerp(ax, bx, t);
float dy = _lerp(ay, by, t);
/* lerp for E */
float ex = _lerp(bx, cx, t);
float ey = _lerp(by, cy, t);
/* sub-arc's control points are tangents of DeCasteljau's algorithm */
if(start) {
arc->p0x = (int32_t)floorf(0.5f + _lerp(dx, ex, t));
arc->p0y = (int32_t)floorf(0.5f + _lerp(dy, ey, t));
arc->p1x = (int32_t)floorf(0.5f + ex);
arc->p1y = (int32_t)floorf(0.5f + ey);
arc->p2x = (int32_t)floorf(0.5f + cx);
arc->p2y = (int32_t)floorf(0.5f + cy);
arc->p3x = fullarc.p3x;
arc->p3y = fullarc.p3y;
}
else {
arc->p0x = fullarc.p0x;
arc->p0y = fullarc.p0y;
arc->p1x = (int32_t)floorf(0.5f + ax);
arc->p1y = (int32_t)floorf(0.5f + ay);
arc->p2x = (int32_t)floorf(0.5f + dx);
arc->p2y = (int32_t)floorf(0.5f + dy);
arc->p3x = (int32_t)floorf(0.5f + _lerp(dx, ex, t));
arc->p3y = (int32_t)floorf(0.5f + _lerp(dy, ey, t));
}
}
/**
* Add the arc control points into the path data for vglite,
* taking into account the real center of the arc (translation).
* arc_path: (in/out) the path data array for vglite
* pidx: (in/out) index of last element added in arc_path
* q_arc: (in) the arc data containing control points
* center: (in) the center of the circle in draw coordinates
* cw: (in) true if arc is clockwise
*/
static void _add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, const lv_point_t * center, bool cw)
{
/* assumes first control point already in array arc_path[] */
int idx = *pidx;
if(cw) {
#if BEZIER_DBG_CONTROL_POINTS
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p3x + center->x;
arc_path[idx++] = q_arc->p3y + center->y;
#else
arc_path[idx++] = VLC_OP_CUBIC;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = q_arc->p3x + center->x;
arc_path[idx++] = q_arc->p3y + center->y;
#endif
}
else { /* reverse points order when counter-clockwise */
#if BEZIER_DBG_CONTROL_POINTS
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p0x + center->x;
arc_path[idx++] = q_arc->p0y + center->y;
#else
arc_path[idx++] = VLC_OP_CUBIC;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = q_arc->p0x + center->x;
arc_path[idx++] = q_arc->p0y + center->y;
#endif
}
/* update index i n path array*/
*pidx = idx;
}
static void _add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw)
{
/* set number of arcs to draw */
vg_arc q_arc;
int32_t start_arc_angle = start_angle % 90;
int32_t end_arc_angle = end_angle % 90;
int32_t inv_start_arc_angle = (start_arc_angle > 0) ? (90 - start_arc_angle) : 0;
int32_t nbarc = (end_angle - start_angle - inv_start_arc_angle - end_arc_angle) / 90;
q_arc.rad = radius;
/* handle special case of start & end point in the same quarter */
if(((start_angle / 90) == (end_angle / 90)) && (nbarc <= 0)) {
q_arc.quarter = (start_angle / 90) % 4;
q_arc.angle = start_arc_angle;
_get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle);
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
return;
}
if(cw) {
/* partial starting arc */
if(start_arc_angle > 0) {
q_arc.quarter = (start_angle / 90) % 4;
q_arc.angle = start_arc_angle;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, true);
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
/* full arcs */
for(int32_t q = 0; q < nbarc ; q++) {
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
q_arc.angle = 90;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
/* partial ending arc */
if(end_arc_angle > 0) {
q_arc.quarter = (end_angle / 90) % 4;
q_arc.angle = end_arc_angle;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, false);
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
}
else { /* counter clockwise */
/* partial ending arc */
if(end_arc_angle > 0) {
q_arc.quarter = (end_angle / 90) % 4;
q_arc.angle = end_arc_angle;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, false);
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
/* full arcs */
for(int32_t q = nbarc - 1; q >= 0; q--) {
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
q_arc.angle = 90;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
/* partial starting arc */
if(start_arc_angle > 0) {
q_arc.quarter = (start_angle / 90) % 4;
q_arc.angle = start_arc_angle;
/* get cubic points relative to center */
_get_arc_control_points(&q_arc, true);
/* put cubic points in arc_path */
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
}
}
}
static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area,
const lv_draw_arc_dsc_t * dsc)
{
vg_lite_path_t path;
uint16_t start_angle = dsc->start_angle;
uint16_t end_angle = dsc->end_angle;
/* be sure end_angle > start_angle */
if(end_angle < start_angle)
end_angle += 360;
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
int32_t arc_path[ARC_PATH_DATA_MAX_SIZE];
lv_memzero(arc_path, sizeof(arc_path));
/*** Init path ***/
int32_t width = dsc->width; /* inner arc radius = outer arc radius - width */
uint16_t radius = dsc->radius;
if(width > radius)
width = radius;
int pidx = 0;
int32_t cp_x, cp_y; /* control point coords */
/* first control point of curve */
cp_x = radius;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_MOVE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
/* draw 1-5 outer quarters */
_add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true);
if(donut) {
/* close outer circle */
cp_x = radius;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
/* start inner circle */
cp_x = radius - width;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_MOVE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
cp_x = radius - width / 2;
cp_y = 0;
_rotate_point(end_angle, &cp_x, &cp_y);
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
_add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180),
&round_center, true);
}
else { /* 1st flat ending */
cp_x = radius - width;
cp_y = 0;
_rotate_point(end_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
/* draw 1-5 inner quarters */
_add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false);
/* last control point of curve */
if(donut) { /* close the loop */
cp_x = radius - width;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
cp_x = radius - width / 2;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
_add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360),
&round_center, true);
}
else { /* 2nd flat ending */
cp_x = radius;
cp_y = 0;
_rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
arc_path[pidx++] = VLC_OP_END;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*** Draw arc ***/
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,203 +0,0 @@
/**
* @file lv_draw_vglite_border.c
*
*/
/**
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_path.h"
#include "lv_vglite_utils.h"
#include <math.h>
/*********************
* DEFINES
*********************/
/*********************
* DEFINES
*********************/
/*** Define maximum numbers of rectangles needed to clip partial borders ***/
#define MAX_NUM_RECTANGLES 4
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Draw rectangle border/outline shape with effects (rounded corners, opacity)
*
* @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff)
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle border/outline
*
*/
static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_border_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(dsc->width == 0)
return;
if(dsc->side == (lv_border_side_t)LV_BORDER_SIDE_NONE)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t inward_coords;
int32_t width = dsc->width;
/* Move border inwards to align with software rendered border */
inward_coords.x1 = coords->x1 + ceil(width / 2.0f);
inward_coords.x2 = coords->x2 - floor(width / 2.0f);
inward_coords.y1 = coords->y1 + ceil(width / 2.0f);
inward_coords.y2 = coords->y2 - floor(width / 2.0f);
lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!lv_area_intersect(&clipped_coords, &inward_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
_vglite_draw_border(&inward_coords, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_border_dsc_t * dsc)
{
int32_t radius = dsc->radius;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
if(radius < 0)
return;
int32_t border_half = (int32_t)floor(dsc->width / 2.0f);
if(radius > border_half)
radius = radius - border_half;
vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
/*** Init path ***/
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
uint32_t path_data_size;
vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
vg_lite_quality_t path_quality = radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
vg_lite_path_t path;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
int32_t line_width = dsc->width;
lv_border_side_t border_side = dsc->side;
if(border_side == LV_BORDER_SIDE_FULL)
border_side = LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT;
uint32_t num_rect = 0;
vg_lite_rectangle_t rect[MAX_NUM_RECTANGLES];
int32_t rect_width = coords->x2 - coords->x1;
int32_t rect_height = coords->y2 - coords->y1;
int32_t shortest_side = LV_MIN(rect_width, rect_height);
int32_t final_radius = LV_MIN(radius, shortest_side / 2);
if(border_side & LV_BORDER_SIDE_TOP) {
rect[num_rect].x = coords->x1 - ceil(line_width / 2.0f);
rect[num_rect].y = coords->y1 - ceil(line_width / 2.0f);
rect[num_rect].width = coords->x2 - coords->x1 + line_width;
rect[num_rect].height = final_radius + ceil(line_width / 2.0f);
num_rect++;
}
if(border_side & LV_BORDER_SIDE_LEFT) {
rect[num_rect].x = coords->x1 - ceil(line_width / 2.0f);
rect[num_rect].y = coords->y1 - ceil(line_width / 2.0f);
rect[num_rect].width = final_radius + ceil(line_width / 2.0f);
rect[num_rect].height = coords->y2 - coords->y1 + line_width + 1;
num_rect++;
}
if(border_side & LV_BORDER_SIDE_RIGHT) {
rect[num_rect].x = coords->x2 - final_radius + 1;
rect[num_rect].y = coords->y1 - ceil(line_width / 2.0f);
rect[num_rect].width = final_radius + ceil(line_width / 2.0f);
rect[num_rect].height = coords->y2 - coords->y1 + line_width + 1;
num_rect++;
}
if(border_side & LV_BORDER_SIDE_BOTTOM) {
rect[num_rect].x = coords->x1 - ceil(line_width / 2.0f);
rect[num_rect].y = coords->y2 - final_radius + 1;
rect[num_rect].width = coords->x2 - coords->x1 + line_width;
rect[num_rect].height = final_radius + ceil(line_width / 2.0f);
num_rect++;
}
/*** Enable scissor and apply scissor rects ***/
VGLITE_CHECK_ERROR(vg_lite_enable_scissor());
VGLITE_CHECK_ERROR(vg_lite_scissor_rects(vgbuf, num_rect, rect));
/*** Draw border ***/
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol));
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
/*** Disable scissor ***/
VGLITE_CHECK_ERROR(vg_lite_disable_scissor());
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,237 +0,0 @@
/**
* @file lv_draw_vglite_fill.c
*
*/
/**
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_path.h"
#include "lv_vglite_utils.h"
#include "../../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Fill area, with optional opacity.
*
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dsc Description of the area to fill (color, opa)
*
*/
static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc);
/**
* Draw rectangle background with effects (rounded corners, gradient)
*
* @param[in] coords Coordinates of the rectangle background (relative to dest buff)
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle background
*
*/
static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_fill_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t relative_coords;
lv_area_copy(&relative_coords, coords);
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!lv_area_intersect(&clipped_coords, &relative_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
/*
* Most simple case: just a plain rectangle (no radius, no gradient)
*/
if((dsc->radius == 0) && (dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE))
_vglite_fill(&clipped_coords, dsc);
else
_vglite_draw_rect(&relative_coords, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc)
{
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
vg_lite_rectangle_t rect = {
.x = dest_area->x1,
.y = dest_area->y1,
.width = lv_area_get_width(dest_area),
.height = lv_area_get_height(dest_area)
};
VGLITE_CHECK_ERROR(vg_lite_clear(vgbuf, &rect, vgcol));
vglite_run();
}
else { /*fill with transparency*/
vg_lite_path_t path;
int32_t path_data[] = { /*VG rectangular path*/
VLC_OP_MOVE, dest_area->x1, dest_area->y1,
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1,
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1,
VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1,
VLC_OP_LINE, dest_area->x1, dest_area->y1,
VLC_OP_END
};
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data,
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*Draw rectangle*/
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
}
static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_fill_dsc_t * dsc)
{
int32_t width = lv_area_get_width(coords);
int32_t height = lv_area_get_height(coords);
int32_t radius = dsc->radius;
lv_opa_t opa = dsc->opa;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
if(dsc->radius < 0)
return;
/*** Init path ***/
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
uint32_t path_data_size;
vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
vg_lite_path_t path;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*** Init Color ***/
lv_color32_t col32 = lv_color_to_32(dsc->color, opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_linear_gradient_t gradient;
bool has_gradient = (dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
/*** Init Gradient ***/
if(has_gradient) {
vg_lite_matrix_t * grad_matrix;
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
/* Gradient setup */
vg_lite_uint32_t cnt = LV_MAX(dsc->grad.stops_count, LV_GRADIENT_MAX_STOPS);
lv_opa_t opa;
for(uint8_t i = 0; i < cnt; i++) {
stops[i] = dsc->grad.stops[i].frac;
opa = LV_OPA_MIX2(dsc->grad.stops[i].opa, dsc->opa);
col32[i] = lv_color_to_32(dsc->grad.stops[i].color, opa);
colors[i] = vglite_get_color(col32[i], true);
}
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
grad_matrix = vg_lite_get_grad_matrix(&gradient);
vg_lite_identity(grad_matrix);
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
if(dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
vg_lite_rotate(90.0f, grad_matrix);
}
else { /*LV_GRAD_DIR_HOR*/
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
}
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
VG_LITE_BLEND_SRC_OVER));
}
else {
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
}
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
if(has_gradient)
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,443 +0,0 @@
/**
* @file lv_draw_vglite_blend.c
*
*/
/**
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_matrix.h"
#include "lv_vglite_utils.h"
#include "lv_vglite_path.h"
#include "../../../misc/lv_log.h"
/*********************
* DEFINES
*********************/
#if LV_USE_VGLITE_BLIT_SPLIT
/**
* BLIT split threshold - BLITs with width or height higher than this value will
* be done in multiple steps. Value must be multiple of stride alignment in px.
* For most color formats the alignment is 16px (except the index formats).
*/
#define VGLITE_BLIT_SPLIT_THR 352
/* Enable for logging debug traces. */
#define VGLITE_LOG_TRACE 0
#if VGLITE_LOG_TRACE
#define VGLITE_TRACE(fmt, ...) \
do { \
LV_LOG(fmt, ##__VA_ARGS__); \
} while (0)
#else
#define VGLITE_TRACE(fmt, ...) \
do { \
} while (0)
#endif
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
#if LV_USE_VGLITE_BLIT_SPLIT
/**
* Move buffer pointer as close as possible to area, but with respect to alignment requirements.
*
* @param[in] buf Buffer address pointer
* @param[in] area Area with relative coordinates to the buffer
* @param[in] stride Stride of buffer in bytes
* @param[in] cf Color format of buffer
*/
static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity.
*
* @param dest_buf Destination buffer
* @param[in] dest_area Destination area with relative coordinates to dest buffer
* @param[in] dest_stride Stride of destination buffer in bytes
* @param[in] dest_cf Color format of destination buffer
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates to src buffer
* @param[in] src_stride Stride of source buffer in bytes
* @param[in] src_cf Color format of source buffer
* @param[in] dsc Image descriptor
*
*/
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
const lv_draw_image_dsc_t * dsc);
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
/**
* VGlite blit - fill a path with an image pattern
*
*
* @param[in] dest_area Destination area with relative coordinates to dest buffer
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] coords Coordinates of the image (relative to dest buff)
* @param[in] dsc Image descriptor
*
*/
static void _vglite_draw_pattern(const lv_area_t * clip_area, const lv_area_t * coords,
const lv_draw_image_dsc_t * dsc);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with or without effects.
*
* @param[in] src_area Source area with relative coordinates to src buffer
* @param[in] dsc Image descriptor
*
*/
static void _vglite_blit(const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc);
static vg_lite_color_t _vglite_recolor(const lv_draw_image_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
const lv_image_dsc_t * img_dsc = dsc->src;
lv_area_t relative_coords;
lv_area_copy(&relative_coords, coords);
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
if(has_transform)
lv_area_copy(&blend_area, &relative_coords);
else if(!lv_area_intersect(&blend_area, &relative_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
const void * src_buf = img_dsc->data;
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
src_area.x2 = img_dsc->header.w - 1;
src_area.y2 = img_dsc->header.h - 1;
lv_color_format_t src_cf = img_dsc->header.cf;
uint32_t src_stride = img_dsc->header.stride;
/* Set src_vgbuf structure. */
vglite_set_src_buf(src_buf, img_dsc->header.w, img_dsc->header.h, src_stride, src_cf);
#if LV_USE_VGLITE_BLIT_SPLIT
void * dest_buf = layer->draw_buf->data;
uint32_t dest_stride = layer->draw_buf->header.stride;
lv_color_format_t dest_cf = layer->draw_buf->header.cf;
if(!has_transform)
_vglite_blit_split(dest_buf, &blend_area, dest_stride, dest_cf,
src_buf, &src_area, src_stride, src_cf, dsc);
#else
vglite_set_transformation_matrix(&blend_area, dsc);
bool is_tiled = dsc->tile;
if(is_tiled)
_vglite_draw_pattern(&clip_area, &relative_coords, dsc);
else
_vglite_blit(&src_area, dsc);
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_blit(const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc)
{
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
vg_lite_buffer_t * src_vgbuf = vglite_get_src_buf();
vg_lite_rectangle_t rect = {
.x = (vg_lite_int32_t)src_area->x1,
.y = (vg_lite_int32_t)src_area->y1,
.width = (vg_lite_int32_t)lv_area_get_width(src_area),
.height = (vg_lite_int32_t)lv_area_get_height(src_area)
};
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
vg_lite_color_t vgcol = _vglite_recolor(dsc);
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, src_vgbuf, &rect, vgmatrix, vgblend, vgcol, VG_LITE_FILTER_POINT));
vglite_run();
}
#if LV_USE_VGLITE_BLIT_SPLIT
static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf)
{
uint8_t ** buf_u8 = (uint8_t **)buf;
uint8_t align_bytes = vglite_get_stride_alignment(cf);
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
area->x1 -= shift_x;
area->x2 -= shift_x;
*buf_u8 += (shift_x * bits_per_pixel) / 8;
}
if(area->y1) {
uint16_t shift_y = area->y1;
area->y1 -= shift_y;
area->y2 -= shift_y;
*buf_u8 += shift_y * stride;
}
}
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
const lv_draw_image_dsc_t * dsc)
{
VGLITE_TRACE("Blit "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf);
/* Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible */
_move_buf_close_to_area((void **)&src_buf, src_area, src_stride, src_cf);
_move_buf_close_to_area(&dest_buf, dest_area, dest_stride, dest_cf);
/* Set clip area */
vglite_set_scissor(dest_area);
/* If we're in limit, do a single BLIT */
if((src_area->x2 < VGLITE_BLIT_SPLIT_THR) &&
(src_area->y2 < VGLITE_BLIT_SPLIT_THR)) {
/* Set new dest_vgbuf and src_vgbuf memory addresses */
vglite_set_dest_buf_ptr(dest_buf);
vglite_set_src_buf_ptr(src_buf);
vglite_set_transformation_matrix(dest_area, dsc);
_vglite_blit(src_area, dsc);
VGLITE_TRACE("Single "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf);
return;
};
/* Split the BLIT into multiple tiles */
VGLITE_TRACE("Split "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf);
int32_t width = LV_MIN(lv_area_get_width(src_area), lv_area_get_width(dest_area));
int32_t height = LV_MIN(lv_area_get_height(src_area), lv_area_get_height(dest_area));
/* Number of tiles needed */
uint8_t total_tiles_x = (src_area->x1 + width + VGLITE_BLIT_SPLIT_THR - 1) /
VGLITE_BLIT_SPLIT_THR;
uint8_t total_tiles_y = (src_area->y1 + height + VGLITE_BLIT_SPLIT_THR - 1) /
VGLITE_BLIT_SPLIT_THR;
uint16_t shift_src_x = src_area->x1;
uint16_t shift_dest_x = dest_area->x1;
VGLITE_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x);
uint8_t * tile_dest_buf;
lv_area_t tile_dest_area;
const uint8_t * tile_src_buf;
lv_area_t tile_src_area;
for(uint8_t y = 0; y < total_tiles_y; y++) {
/* y1 always start from 0 */
tile_src_area.y1 = 0;
/* Calculate y2 coordinates */
if(y < total_tiles_y - 1)
tile_src_area.y2 = VGLITE_BLIT_SPLIT_THR - 1;
else
tile_src_area.y2 = height - y * VGLITE_BLIT_SPLIT_THR - 1;
/* No vertical shift, dest y is always in sync with src y */
tile_dest_area.y1 = tile_src_area.y1;
tile_dest_area.y2 = tile_src_area.y2;
/* Advance start pointer for every tile, except the first column (y = 0) */
tile_src_buf = (uint8_t *)src_buf + y * VGLITE_BLIT_SPLIT_THR * src_stride;
tile_dest_buf = (uint8_t *)dest_buf + y * VGLITE_BLIT_SPLIT_THR * dest_stride;
for(uint8_t x = 0; x < total_tiles_x; x++) {
/* x1 always start from the same shift */
tile_src_area.x1 = shift_src_x;
tile_dest_area.x1 = shift_dest_x;
if(x > 0) {
/* Advance start pointer for every tile, except the first raw (x = 0) */
tile_src_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(src_cf) / 8;
tile_dest_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(dest_cf) / 8;
}
/* Calculate x2 coordinates */
if(x < total_tiles_x - 1)
tile_src_area.x2 = VGLITE_BLIT_SPLIT_THR - 1;
else
tile_src_area.x2 = width - x * VGLITE_BLIT_SPLIT_THR - 1;
tile_dest_area.x2 = tile_src_area.x2;
/* Shift x2 coordinates */
tile_src_area.x2 += shift_src_x;
tile_dest_area.x2 += shift_dest_x;
/* Set new dest_vgbuf and src_vgbuf memory addresses */
vglite_set_dest_buf_ptr(tile_dest_buf);
vglite_set_src_buf_ptr(tile_src_buf);
vglite_set_transformation_matrix(&tile_dest_area, dsc);
_vglite_blit(&tile_src_area, dsc);
VGLITE_TRACE("Tile [%d, %d] "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
x, y,
tile_src_area.x1, tile_src_area.y1, tile_src_area.x2, tile_src_area.y2,
tile_dest_area.x1, tile_dest_area.y1, tile_dest_area.x2, tile_dest_area.y2,
lv_area_get_width(&tile_src_area), lv_area_get_height(&tile_src_area),
lv_area_get_width(&tile_dest_area), lv_area_get_height(&tile_dest_area),
(uintptr_t)tile_src_buf, (uintptr_t)tile_dest_buf);
}
}
}
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
static void _vglite_draw_pattern(const lv_area_t * clip_area, const lv_area_t * coords,
const lv_draw_image_dsc_t * dsc)
{
/* Target buffer */
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
/* Path to draw */
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
uint32_t path_data_size;
vglite_create_rect_path_data(path_data, &path_data_size, dsc->clip_radius, coords);
vg_lite_quality_t path_quality = VG_LITE_MEDIUM;
vg_lite_path_t path;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
/* Path Matrix */
vg_lite_matrix_t path_matrix;
vg_lite_identity(&path_matrix);
/* Pattern Image */
vg_lite_buffer_t * src_vgbuf = vglite_get_src_buf();
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
/* Pattern matrix */
vg_lite_matrix_t vgmatrix;
vg_lite_identity(&vgmatrix);
vg_lite_translate((vg_lite_float_t)dsc->image_area.x1, (vg_lite_float_t)dsc->image_area.y1, &vgmatrix);
/* Blend mode */
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
vg_lite_color_t vgcol = _vglite_recolor(dsc);
/* Filter */
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
vg_lite_filter_t filter = has_transform ? VG_LITE_FILTER_BI_LINEAR : VG_LITE_FILTER_POINT;
/* Draw Pattern */
VGLITE_CHECK_ERROR(vg_lite_draw_pattern(dst_vgbuf, &path, VG_LITE_FILL_NON_ZERO, &path_matrix,
src_vgbuf, &vgmatrix, vgblend, VG_LITE_PATTERN_REPEAT,
0, vgcol, filter));
}
static vg_lite_color_t _vglite_recolor(const lv_draw_image_dsc_t * dsc)
{
lv_color_t color;
lv_opa_t opa;
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
if(has_recolor) {
color = dsc->recolor;
opa = LV_OPA_MIX2(dsc->recolor_opa, dsc->opa);
}
else {
color.red = 0xFF;
color.green = 0xFF;
color.blue = 0xFF;
opa = dsc->opa;
}
lv_color32_t col32 = lv_color_to_32(color, opa);
return vglite_get_color(col32, false);
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,180 +0,0 @@
/**
* @file lv_draw_vglite_label.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_matrix.h"
#include "lv_vglite_utils.h"
#include "../../lv_draw_label_private.h"
#include "../../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
/**
* Draw letter (character bitmap blend) with optional color and opacity
*
* @param[in] mask_area Mask area with relative coordinates of source buffer
* @param[in] color Color
* @param[in] opa Opacity
*
*/
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->opa <= LV_OPA_MIN) return;
lv_draw_label_iterate_characters(draw_unit, dsc, coords, _draw_vglite_letter);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
{
if(glyph_draw_dsc) {
switch(glyph_draw_dsc->format) {
case LV_FONT_GLYPH_FORMAT_NONE: {
#if LV_USE_FONT_PLACEHOLDER
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
#endif
}
break;
case LV_FONT_GLYPH_FORMAT_A1 ... LV_FONT_GLYPH_FORMAT_A8: {
/*Do not draw transparent things*/
if(glyph_draw_dsc->opa <= LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t blend_area;
if(!lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area))
return;
lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1);
const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
const void * mask_buf = draw_buf->data;
uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords);
uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords);
uint32_t mask_stride = draw_buf->header.stride;
lv_area_t mask_area;
mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1);
mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1);
mask_area.x2 = mask_width - 1;
mask_area.y2 = mask_height - 1;
/* Set src_vgbuf structure. */
vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8);
/* Set vgmatrix. */
vglite_set_translation_matrix(&blend_area);
lv_draw_buf_invalidate_cache(draw_buf, &mask_area);
_vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa);
}
break;
case LV_FONT_GLYPH_FORMAT_IMAGE: {
#if LV_USE_IMGFONT
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.opa = glyph_draw_dsc->opa;
img_dsc.src = glyph_draw_dsc->glyph_data;
lv_draw_vglite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
#endif
}
break;
default:
break;
}
}
if(fill_draw_dsc && fill_area) {
lv_draw_vglite_fill(draw_unit, fill_draw_dsc, fill_area);
}
}
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa)
{
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
vg_lite_buffer_t * mask_vgbuf = vglite_get_src_buf();
mask_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
mask_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
vg_lite_rectangle_t rect = {
.x = (vg_lite_int32_t)mask_area->x1,
.y = (vg_lite_int32_t)mask_area->y1,
.width = (vg_lite_int32_t)lv_area_get_width(mask_area),
.height = (vg_lite_int32_t)lv_area_get_height(mask_area)
};
lv_color32_t col32 = lv_color_to_32(color, opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
/*Blit with font color as paint color*/
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, mask_vgbuf, &rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol,
VG_LITE_FILTER_POINT));
vglite_run();
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,157 +0,0 @@
/**
* @file lv_draw_vglite_layer.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "../../../stdlib/lv_string.h"
#include "../../../core/lv_global.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords)
{
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
const lv_draw_buf_t * draw_buf = layer_to_draw->draw_buf;
/* It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
* In this case just return.
*/
if(draw_buf == NULL)
return;
if(_draw_info.unit_cnt > 1) {
const lv_area_t area_to_draw = {
.x1 = 0,
.y1 = 0,
.x2 = draw_buf->header.w - 1,
.y2 = draw_buf->header.h - 1
};
lv_draw_buf_invalidate_cache(draw_buf, &area_to_draw);
}
lv_draw_image_dsc_t new_draw_dsc = *draw_dsc;
new_draw_dsc.src = draw_buf;
lv_draw_vglite_img(draw_unit, &new_draw_dsc, coords);
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
lv_area_t area_rot;
lv_area_copy(&area_rot, coords);
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
if(has_transform) {
int32_t w = lv_area_get_width(coords);
int32_t h = lv_area_get_height(coords);
lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
&draw_dsc->pivot);
area_rot.x1 += coords->x1;
area_rot.y1 += coords->y1;
area_rot.x2 += coords->x1;
area_rot.y2 += coords->y1;
}
lv_area_t draw_area;
if(!lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
#endif
#if LV_USE_LAYER_DEBUG
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
fill_dsc.opa = LV_OPA_20;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = fill_dsc.color;
border_dsc.opa = LV_OPA_60;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
#endif
#if LV_USE_PARALLEL_DRAW_DEBUG
uint32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != draw_unit) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_fill_dsc_t fill_dsc;
lv_draw_rect_dsc_init(&fill_dsc);
fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
fill_dsc.opa = LV_OPA_10;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
border_dsc.opa = LV_OPA_100;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y2;
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_black();
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_white();
label_dsc.text = buf;
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
#endif
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,145 +0,0 @@
/**
* @file lv_draw_vglite_line.c
*
*/
/**
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Draw line shape with effects
*
* @param[in] point1 Starting point with relative coordinates
* @param[in] point2 Ending point with relative coordinates
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
*
*/
static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc)
{
if(dsc->width == 0)
return;
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t clip_area;
clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
if(!lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area))
return; /*Fully clipped, nothing to do*/
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1};
lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1};
_vglite_draw_line(&point1, &point2, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc)
{
vg_lite_path_t path;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
vg_lite_join_style_t join_style = (dsc->round_start || dsc->round_end) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
bool is_dashed = (dsc->dash_width && dsc->dash_gap);
vg_lite_float_t stroke_dash_pattern[2] = {0, 0};
uint32_t stroke_dash_count = 0;
vg_lite_float_t stroke_dash_phase = 0;
if(is_dashed) {
stroke_dash_pattern[0] = (vg_lite_float_t)dsc->dash_width;
stroke_dash_pattern[1] = (vg_lite_float_t)dsc->dash_gap;
stroke_dash_count = sizeof(stroke_dash_pattern) / sizeof(vg_lite_float_t);
stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2;
}
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
/*** Init path ***/
int32_t width = dsc->width;
int32_t line_path[] = { /*VG line path*/
VLC_OP_MOVE, point1->x, point1->y,
VLC_OP_LINE, point2->x, point2->y,
VLC_OP_END
};
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*** Draw line ***/
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
stroke_dash_phase, vgcol));
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vgblend, vgcol));
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,182 +0,0 @@
/**
* @file lv_draw_vglite_triangle.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_path.h"
#include "lv_vglite_utils.h"
#include "../../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Draw triangle shape with effects (opacity, gradient)
*
* @param[in] coords Coordinates of the triangle (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the triangle
*
*/
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_triangle_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc)
{
if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t coords;
coords.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
coords.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
coords.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
coords.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
lv_area_move(&coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!lv_area_intersect(&clipped_coords, &coords, &clip_area))
return; /* Fully clipped, nothing to do */
_vglite_draw_triangle(&coords, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_triangle_dsc_t * dsc)
{
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
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);
uint32_t width = lv_area_get_width(&tri_area);
uint32_t height = lv_area_get_height(&tri_area);
/* Init path */
int32_t triangle_path[] = { /*VG line path*/
VLC_OP_MOVE, dsc->p[0].x, dsc->p[0].y,
VLC_OP_LINE, dsc->p[1].x, dsc->p[1].y,
VLC_OP_LINE, dsc->p[2].x, dsc->p[2].y,
VLC_OP_LINE, dsc->p[0].x, dsc->p[0].y,
VLC_OP_END
};
vg_lite_path_t path;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(triangle_path), triangle_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/* Init Color */
lv_color32_t col32 = lv_color_to_32(dsc->bg_color, dsc->bg_opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_linear_gradient_t gradient;
bool has_gradient = (dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
/* Init Gradient*/
if(has_gradient) {
vg_lite_matrix_t * grad_matrix;
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
/* Gradient Setup */
vg_lite_uint32_t cnt = LV_MAX(dsc->bg_grad.stops_count, LV_GRADIENT_MAX_STOPS);
lv_opa_t bg_opa;
for(uint8_t i = 0; i < cnt; i++) {
stops[i] = dsc->bg_grad.stops[i].frac;
bg_opa = LV_OPA_MIX2(dsc->bg_grad.stops[i].opa, dsc->bg_opa);
col32[i] = lv_color_to_32(dsc->bg_grad.stops[i].color, bg_opa);
colors[i] = vglite_get_color(col32[i], true);
}
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
grad_matrix = vg_lite_get_grad_matrix(&gradient);
vg_lite_identity(grad_matrix);
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
vg_lite_rotate(90.0f, grad_matrix);
}
else { /*LV_GRAD_DIR_HOR*/
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
}
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
VG_LITE_BLEND_SRC_OVER));
}
else {
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
}
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
if(has_gradient)
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,116 +0,0 @@
/**
* @file lv_vglite_buf.c
*
*/
/**
* Copyright 2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_vglite_buf.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_utils.h"
#include "../../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf);
/**********************
* STATIC VARIABLES
**********************/
static vg_lite_buffer_t _dest_vgbuf;
static vg_lite_buffer_t _src_vgbuf;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
vg_lite_buffer_t * vglite_get_dest_buf(void)
{
return &_dest_vgbuf;
}
vg_lite_buffer_t * vglite_get_src_buf(void)
{
return &_src_vgbuf;
}
void vglite_set_dest_buf_ptr(void * buf)
{
_set_vgbuf_ptr(&_dest_vgbuf, buf);
}
void vglite_set_src_buf_ptr(const void * buf)
{
_set_vgbuf_ptr(&_src_vgbuf, (void *)buf);
}
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vglite_set_buf(&_dest_vgbuf, (void *)buf, width, height, stride, cf);
}
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vglite_set_buf(&_src_vgbuf, (void *)buf, width, height, stride, cf);
}
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vg_lite_buffer_format_t vgformat = vglite_get_buf_format(cf);
vgbuf->format = vgformat;
vgbuf->tiled = VG_LITE_LINEAR;
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
vgbuf->width = (int32_t)width;
vgbuf->height = (int32_t)height;
vgbuf->stride = (int32_t)stride;
lv_memzero(&vgbuf->yuv, sizeof(vgbuf->yuv));
vgbuf->memory = buf;
vgbuf->address = (uint32_t)vgbuf->memory;
vgbuf->handle = NULL;
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf)
{
vgbuf->memory = buf;
vgbuf->address = (uint32_t)vgbuf->memory;
}
#endif /*LV_USE_DRAW_VGLITE*/

View File

@@ -1,124 +0,0 @@
/**
* @file lv_vglite_buf.h
*
*/
/**
* Copyright 2023 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_VGLITE_BUF_H
#define LV_VGLITE_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_VGLITE
#include "../../sw/lv_draw_sw.h"
#include "vg_lite.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Get vglite destination buffer pointer.
*
* @retval The vglite destination buffer
*
*/
vg_lite_buffer_t * vglite_get_dest_buf(void);
/**
* Get vglite source buffer pointer.
*
* @retval The vglite source buffer
*
*/
vg_lite_buffer_t * vglite_get_src_buf(void);
/**
* Set vglite destination buffer address only.
*
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
*
*/
void vglite_set_dest_buf_ptr(void * buf);
/**
* Set vglite source buffer address only.
*
* @param[in] buf Source buffer address
*
*/
void vglite_set_src_buf_ptr(const void * buf);
/**
* Set vglite destination buffer.
*
* @param[in] buf Destination buffer address
* @param[in] width Destination buffer width
* @param[in] height Destination buffer height
* @param[in] stride Destination buffer stride in bytes
* @param[in] cf Destination buffer color format
*
*/
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**
* Set vglite source buffer.
*
* @param[in] buf Source buffer address
* @param[in] width Source buffer width
* @param[in] height Source buffer height
* @param[in] stride Source buffer stride in bytes
* @param[in] cf Source buffer color format
*
*/
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**
* Set vglite buffer.
*
* @param[in] vgbuf Address of the VGLite buffer object
* @param[in] buf Address of the memory for the VGLite buffer
* @param[in] width Buffer width
* @param[in] height Buffer height
* @param[in] stride Buffer stride in bytes
* @param[in] cf Buffer color format
*
*/
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_VGLITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_VGLITE_BUF_H*/

View File

@@ -1,81 +0,0 @@
/**
* @file lv_vglite_matrix.c
*
*/
/**
* Copyright 2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_vglite_matrix.h"
#if LV_USE_DRAW_VGLITE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static vg_lite_matrix_t _vgmatrix;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
vg_lite_matrix_t * vglite_get_matrix(void)
{
return &_vgmatrix;
}
void vglite_set_translation_matrix(const lv_area_t * dest_area)
{
vg_lite_identity(&_vgmatrix);
vg_lite_translate((vg_lite_float_t)dest_area->x1, (vg_lite_float_t)dest_area->y1, &_vgmatrix);
}
void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_image_dsc_t * dsc)
{
vglite_set_translation_matrix(dest_area);
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
bool has_rotation = (dsc->rotation != 0);
if(has_scale || has_rotation) {
vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &_vgmatrix);
if(has_rotation)
vg_lite_rotate(dsc->rotation / 10.0f, &_vgmatrix); /* angle is 1/10 degree */
if(has_scale) {
vg_lite_float_t scale_x = 1.0f * dsc->scale_x / LV_SCALE_NONE;
vg_lite_float_t scale_y = 1.0f * dsc->scale_y / LV_SCALE_NONE;
vg_lite_scale(scale_x, scale_y, &_vgmatrix);
}
vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &_vgmatrix);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_VGLITE*/

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