init lvgl code
This commit is contained in:
20
LVGL.Simulator/lvgl/src/core/lv_core.mk
Normal file
20
LVGL.Simulator/lvgl/src/core/lv_core.mk
Normal file
@@ -0,0 +1,20 @@
|
||||
CSRCS += lv_disp.c
|
||||
CSRCS += lv_group.c
|
||||
CSRCS += lv_indev.c
|
||||
CSRCS += lv_indev_scroll.c
|
||||
CSRCS += lv_obj.c
|
||||
CSRCS += lv_obj_class.c
|
||||
CSRCS += lv_obj_draw.c
|
||||
CSRCS += lv_obj_pos.c
|
||||
CSRCS += lv_obj_scroll.c
|
||||
CSRCS += lv_obj_style.c
|
||||
CSRCS += lv_obj_style_gen.c
|
||||
CSRCS += lv_obj_tree.c
|
||||
CSRCS += lv_event.c
|
||||
CSRCS += lv_refr.c
|
||||
CSRCS += lv_theme.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core"
|
||||
490
LVGL.Simulator/lvgl/src/core/lv_disp.c
Normal file
490
LVGL.Simulator/lvgl/src/core/lv_disp.c
Normal file
@@ -0,0 +1,490 @@
|
||||
/**
|
||||
* @file lv_disp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void scr_load_anim_start(lv_anim_t * a);
|
||||
static void opa_scale_anim(void * obj, int32_t v);
|
||||
static void set_x_anim(void * obj, int32_t v);
|
||||
static void set_y_anim(void * obj, int32_t v);
|
||||
static void scr_anim_ready(lv_anim_t * a);
|
||||
static bool is_out_anim(lv_scr_load_anim_t a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with a pointer to the active screen
|
||||
* @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_scr_load()')
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its active screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->act_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_disp_get_scr_prev(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its previous screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->prev_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a screen active
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_disp_load_scr(lv_obj_t * scr)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(scr);
|
||||
if(!d) return; /*Shouldn't happen, just to be sure*/
|
||||
|
||||
lv_obj_t * old_scr = d->act_scr;
|
||||
|
||||
if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||
if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||
|
||||
d->act_scr = scr;
|
||||
|
||||
if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL);
|
||||
if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||
|
||||
lv_obj_invalidate(scr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the top layer. (Same on every screen 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 (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->top_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the sys. layer. (Same on every 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 (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->sys_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the theme of a display
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->theme = th;
|
||||
|
||||
if(disp->screen_cnt == 3 &&
|
||||
lv_obj_get_child_cnt(disp->screens[0]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[1]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[2]) == 0) {
|
||||
lv_theme_apply(disp->screens[0]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the theme of a display
|
||||
* @param disp pointer to a display
|
||||
* @return the display's theme (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_disp_get_theme(lv_disp_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_disp_get_default();
|
||||
return disp->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background color of a display
|
||||
* @param disp pointer to a display
|
||||
* @param color color of the background
|
||||
*/
|
||||
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_color = color;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background image of a display
|
||||
* @param disp pointer to a display
|
||||
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
|
||||
*/
|
||||
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_img = img_src;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set opacity of the background
|
||||
* @param disp pointer to a display
|
||||
* @param opa opacity (0..255)
|
||||
*/
|
||||
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_opa = opa;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch screen with animation
|
||||
* @param scr pointer to the new screen to load
|
||||
* @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
|
||||
* @param time time of the animation
|
||||
* @param delay delay before the transition
|
||||
* @param auto_del true: automatically delete the old screen
|
||||
*/
|
||||
void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del)
|
||||
{
|
||||
|
||||
lv_disp_t * d = lv_obj_get_disp(new_scr);
|
||||
lv_obj_t * act_scr = lv_scr_act();
|
||||
|
||||
/*If an other screen load animation is in progress
|
||||
*make target screen loaded immediately. */
|
||||
if(d->scr_to_load && act_scr != d->scr_to_load) {
|
||||
lv_disp_load_scr(d->scr_to_load);
|
||||
lv_anim_del(d->scr_to_load, NULL);
|
||||
lv_obj_set_pos(d->scr_to_load, 0, 0);
|
||||
lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0);
|
||||
|
||||
if(d->del_prev) {
|
||||
lv_obj_del(act_scr);
|
||||
}
|
||||
act_scr = d->scr_to_load;
|
||||
}
|
||||
|
||||
d->scr_to_load = new_scr;
|
||||
|
||||
if(d->prev_scr && d->del_prev) {
|
||||
lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
}
|
||||
|
||||
d->draw_prev_over_act = is_out_anim(anim_type);
|
||||
d->del_prev = auto_del;
|
||||
|
||||
/*Be sure there is no other animation on the screens*/
|
||||
lv_anim_del(new_scr, NULL);
|
||||
lv_anim_del(lv_scr_act(), NULL);
|
||||
|
||||
/*Be sure both screens are in a normal position*/
|
||||
lv_obj_set_pos(new_scr, 0, 0);
|
||||
lv_obj_set_pos(lv_scr_act(), 0, 0);
|
||||
lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0);
|
||||
lv_obj_remove_local_style_prop(lv_scr_act(), LV_STYLE_OPA, 0);
|
||||
|
||||
lv_anim_t a_new;
|
||||
lv_anim_init(&a_new);
|
||||
lv_anim_set_var(&a_new, new_scr);
|
||||
lv_anim_set_start_cb(&a_new, scr_load_anim_start);
|
||||
lv_anim_set_ready_cb(&a_new, scr_anim_ready);
|
||||
lv_anim_set_time(&a_new, time);
|
||||
lv_anim_set_delay(&a_new, delay);
|
||||
|
||||
lv_anim_t a_old;
|
||||
lv_anim_init(&a_old);
|
||||
lv_anim_set_var(&a_old, d->act_scr);
|
||||
lv_anim_set_time(&a_old, time);
|
||||
lv_anim_set_delay(&a_old, delay);
|
||||
|
||||
switch(anim_type) {
|
||||
case LV_SCR_LOAD_ANIM_NONE:
|
||||
/*Create a dummy animation to apply the delay*/
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, 0, 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_FADE_IN:
|
||||
lv_anim_set_exec_cb(&a_new, opa_scale_anim);
|
||||
lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_FADE_OUT:
|
||||
lv_anim_set_exec_cb(&a_old, opa_scale_anim);
|
||||
lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_LEFT:
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_TOP:
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OUT_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
|
||||
break;
|
||||
}
|
||||
|
||||
lv_event_send(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||
|
||||
lv_anim_start(&a_new);
|
||||
lv_anim_start(&a_old);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_disp_get_inactive_time(const lv_disp_t * disp)
|
||||
{
|
||||
if(disp) return lv_tick_elaps(disp->last_activity_time);
|
||||
|
||||
lv_disp_t * d;
|
||||
uint32_t t = UINT32_MAX;
|
||||
d = lv_disp_get_next(NULL);
|
||||
while(d) {
|
||||
uint32_t elaps = lv_tick_elaps(d->last_activity_time);
|
||||
t = LV_MIN(t, elaps);
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually trigger an activity on a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_trig_activity(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_trig_activity: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->last_activity_time = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean any CPU cache that is related to the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_clean_dcache(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_clean_dcache: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->driver->clean_dcache_cb)
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_disp_get_refr_timer(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_get_refr_timer: no display registered");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->refr_timer;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void scr_load_anim_start(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
|
||||
d->prev_scr = lv_scr_act();
|
||||
d->act_scr = a->var;
|
||||
|
||||
lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||
}
|
||||
|
||||
static void opa_scale_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void set_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_x(obj, v);
|
||||
}
|
||||
|
||||
static void set_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_y(obj, v);
|
||||
}
|
||||
|
||||
static void scr_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
|
||||
lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL);
|
||||
lv_event_send(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||
|
||||
if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
d->draw_prev_over_act = false;
|
||||
d->scr_to_load = NULL;
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
}
|
||||
|
||||
static bool is_out_anim(lv_scr_load_anim_t anim_type)
|
||||
{
|
||||
return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_TOP ||
|
||||
anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM;
|
||||
}
|
||||
250
LVGL.Simulator/lvgl/src/core/lv_disp.h
Normal file
250
LVGL.Simulator/lvgl/src/core/lv_disp.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* @file lv_disp.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DISP_H
|
||||
#define LV_DISP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../hal/lv_hal.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
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_scr_load_anim_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with a pointer to the active screen
|
||||
* @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_scr_load()')
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_act(lv_disp_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_disp_get_scr_prev(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Make a screen active
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_disp_load_scr(lv_obj_t * scr);
|
||||
|
||||
/**
|
||||
* Return with the top layer. (Same on every screen 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 (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Return with the sys. layer. (Same on every 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 (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Set the theme of a display
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_disp_set_theme(lv_disp_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_disp_get_theme(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Set the background color of a display
|
||||
* @param disp pointer to a display
|
||||
* @param color color of the background
|
||||
*/
|
||||
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the background image of a display
|
||||
* @param disp pointer to a display
|
||||
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
|
||||
*/
|
||||
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src);
|
||||
|
||||
/**
|
||||
* Set opacity of the background
|
||||
* @param disp pointer to a display
|
||||
* @param opa opacity (0..255)
|
||||
*/
|
||||
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Switch screen with animation
|
||||
* @param scr pointer to the new screen to load
|
||||
* @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
|
||||
* @param time time of the animation
|
||||
* @param delay delay before the transition
|
||||
* @param auto_del true: automatically delete the old screen
|
||||
*/
|
||||
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);
|
||||
|
||||
/**
|
||||
* 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_disp_get_inactive_time(const lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Manually trigger an activity on a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_trig_activity(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Clean any CPU cache that is related to the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_clean_dcache(lv_disp_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_disp_get_refr_timer(lv_disp_t * disp);
|
||||
|
||||
/*------------------------------------------------
|
||||
* To improve backward compatibility
|
||||
* Recommended only if you have one display
|
||||
*------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Get the active screen of the default display
|
||||
* @return pointer to the active screen
|
||||
*/
|
||||
static inline lv_obj_t * lv_scr_act(void)
|
||||
{
|
||||
return lv_disp_get_scr_act(lv_disp_get_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top layer of the default display
|
||||
* @return pointer to the top layer
|
||||
*/
|
||||
static inline lv_obj_t * lv_layer_top(void)
|
||||
{
|
||||
return lv_disp_get_layer_top(lv_disp_get_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active screen of the default display
|
||||
* @return pointer to the sys layer
|
||||
*/
|
||||
static inline lv_obj_t * lv_layer_sys(void)
|
||||
{
|
||||
return lv_disp_get_layer_sys(lv_disp_get_default());
|
||||
}
|
||||
|
||||
static inline void lv_scr_load(lv_obj_t * scr)
|
||||
{
|
||||
lv_disp_load_scr(scr);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* 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_disp_get_hor_res(lv_disp_get_default())
|
||||
#endif
|
||||
|
||||
#ifndef LV_VER_RES
|
||||
/**
|
||||
* The vertical resolution of the currently active display.
|
||||
*/
|
||||
#define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default())
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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`
|
||||
*/
|
||||
static inline lv_coord_t lv_dpx(lv_coord_t n)
|
||||
{
|
||||
return LV_DPX(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 obj a display whose dpi should be considered
|
||||
* @param n the number of pixels to scale
|
||||
* @return `n x current_dpi/160`
|
||||
*/
|
||||
static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n)
|
||||
{
|
||||
return _LV_DPX_CALC(lv_disp_get_dpi(disp), n);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DISP_H*/
|
||||
527
LVGL.Simulator/lvgl/src/core/lv_event.c
Normal file
527
LVGL.Simulator/lvgl/src/core/lv_event.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/**
|
||||
* @file lv_event.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_event_dsc_t {
|
||||
lv_event_cb_t cb;
|
||||
void * user_data;
|
||||
lv_event_code_t filter : 8;
|
||||
} lv_event_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id);
|
||||
static lv_res_t event_send_core(lv_event_t * e);
|
||||
static bool event_is_bubbled(lv_event_t * e);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_event_t * event_head;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_LOG_TRACE_EVENT
|
||||
#define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define EVENT_TRACE(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
|
||||
{
|
||||
if(obj == NULL) return LV_RES_OK;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_event_t e;
|
||||
e.target = obj;
|
||||
e.current_target = obj;
|
||||
e.code = event_code;
|
||||
e.user_data = NULL;
|
||||
e.param = param;
|
||||
e.deleted = 0;
|
||||
e.stop_bubbling = 0;
|
||||
e.stop_processing = 0;
|
||||
|
||||
/*Build a simple linked list from the objects used in the events
|
||||
*It's important to know if this object was deleted by a nested event
|
||||
*called from this `event_cb`.*/
|
||||
e.prev = event_head;
|
||||
event_head = &e;
|
||||
|
||||
/*Send the event*/
|
||||
lv_res_t res = event_send_core(&e);
|
||||
|
||||
/*Remove this element from the list*/
|
||||
event_head = e.prev;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_res_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 = 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_RES_OK;
|
||||
if(base->event_cb == NULL) return LV_RES_OK;
|
||||
|
||||
/*Call the actual event callback*/
|
||||
e->user_data = NULL;
|
||||
base->event_cb(base, e);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) res = LV_RES_INV;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t * lv_event_get_target(lv_event_t * e)
|
||||
{
|
||||
return e->target;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_event_get_current_target(lv_event_t * e)
|
||||
{
|
||||
return e->current_target;
|
||||
}
|
||||
|
||||
lv_event_code_t lv_event_get_code(lv_event_t * e)
|
||||
{
|
||||
return e->code & ~LV_EVENT_PREPROCESS;
|
||||
}
|
||||
|
||||
void * lv_event_get_param(lv_event_t * e)
|
||||
{
|
||||
return e->param;
|
||||
}
|
||||
|
||||
void * lv_event_get_user_data(lv_event_t * e)
|
||||
{
|
||||
return e->user_data;
|
||||
}
|
||||
|
||||
void lv_event_stop_bubbling(lv_event_t * e)
|
||||
{
|
||||
e->stop_bubbling = 1;
|
||||
}
|
||||
|
||||
void lv_event_stop_processing(lv_event_t * e)
|
||||
{
|
||||
e->stop_processing = 1;
|
||||
}
|
||||
|
||||
|
||||
uint32_t lv_event_register_id(void)
|
||||
{
|
||||
static uint32_t last_id = _LV_EVENT_LAST;
|
||||
last_id ++;
|
||||
return last_id;
|
||||
}
|
||||
|
||||
void _lv_event_mark_deleted(lv_obj_t * obj)
|
||||
{
|
||||
lv_event_t * e = event_head;
|
||||
|
||||
while(e) {
|
||||
if(e->current_target == obj || e->target == obj) e->deleted = 1;
|
||||
e = e->prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct _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);
|
||||
|
||||
obj->spec_attr->event_dsc_cnt++;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data;
|
||||
|
||||
return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1];
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) &&
|
||||
obj->spec_attr->event_dsc[i].user_data == user_data) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(&obj->spec_attr->event_dsc[i] == event_dsc) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(event_cb == obj->spec_attr->event_dsc[i].cb) return obj->spec_attr->event_dsc[i].user_data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_PART_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_PART_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_ctx_t * lv_event_get_draw_ctx(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;
|
||||
}
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size)
|
||||
{
|
||||
if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_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");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!obj->spec_attr) return NULL;
|
||||
if(id >= obj->spec_attr->event_dsc_cnt) return NULL;
|
||||
|
||||
return &obj->spec_attr->event_dsc[id];
|
||||
}
|
||||
|
||||
static lv_res_t event_send_core(lv_event_t * e)
|
||||
{
|
||||
EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param);
|
||||
|
||||
/*Call the input device's feedback callback if set*/
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
if(indev_act) {
|
||||
if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code);
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0);
|
||||
|
||||
uint32_t i = 0;
|
||||
while(event_dsc && res == LV_RES_OK) {
|
||||
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == LV_EVENT_PREPROCESS)
|
||||
&& (event_dsc->filter == (LV_EVENT_ALL | LV_EVENT_PREPROCESS) ||
|
||||
(event_dsc->filter & ~LV_EVENT_PREPROCESS) == e->code)) {
|
||||
e->user_data = event_dsc->user_data;
|
||||
event_dsc->cb(e);
|
||||
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
i++;
|
||||
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
|
||||
}
|
||||
|
||||
res = lv_obj_event_base(NULL, e);
|
||||
|
||||
event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0);
|
||||
|
||||
i = 0;
|
||||
while(event_dsc && res == LV_RES_OK) {
|
||||
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == 0)
|
||||
&& (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
|
||||
e->user_data = event_dsc->user_data;
|
||||
event_dsc->cb(e);
|
||||
|
||||
if(e->stop_processing) return LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
i++;
|
||||
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
|
||||
}
|
||||
|
||||
if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e)) {
|
||||
e->current_target = e->current_target->parent;
|
||||
res = event_send_core(e);
|
||||
if(res != LV_RES_OK) return LV_RES_INV;
|
||||
}
|
||||
|
||||
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_PART_BEGIN:
|
||||
case LV_EVENT_DRAW_PART_END:
|
||||
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;
|
||||
}
|
||||
}
|
||||
363
LVGL.Simulator/lvgl/src/core/lv_event.h
Normal file
363
LVGL.Simulator/lvgl/src/core/lv_event.h
Normal file
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @file lv_event.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EVENT_H
|
||||
#define LV_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_event_dsc_t;
|
||||
|
||||
/**
|
||||
* Type of event being sent to the object.
|
||||
*/
|
||||
typedef enum {
|
||||
LV_EVENT_ALL = 0,
|
||||
|
||||
/** Input device events*/
|
||||
LV_EVENT_PRESSED, /**< The object has been pressed*/
|
||||
LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/
|
||||
LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */
|
||||
LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/
|
||||
LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/
|
||||
LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/
|
||||
LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/
|
||||
LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/
|
||||
LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/
|
||||
LV_EVENT_SCROLL_END, /**< Scrolling ends*/
|
||||
LV_EVENT_SCROLL, /**< Scrolling*/
|
||||
LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */
|
||||
LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/
|
||||
LV_EVENT_FOCUSED, /**< The object is focused*/
|
||||
LV_EVENT_DEFOCUSED, /**< The object is defocused*/
|
||||
LV_EVENT_LEAVE, /**< The object is defocused but still selected*/
|
||||
LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/
|
||||
|
||||
/** Drawing events*/
|
||||
LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/
|
||||
LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/
|
||||
LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/
|
||||
LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/
|
||||
LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/
|
||||
LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
|
||||
LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
|
||||
|
||||
/** Special events*/
|
||||
LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/
|
||||
LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/
|
||||
LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/
|
||||
LV_EVENT_READY, /**< A process has finished*/
|
||||
LV_EVENT_CANCEL, /**< A process has been cancelled */
|
||||
|
||||
/** Other events*/
|
||||
LV_EVENT_DELETE, /**< Object is being deleted*/
|
||||
LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */
|
||||
LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/
|
||||
LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/
|
||||
LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/
|
||||
LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/
|
||||
LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/
|
||||
LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/
|
||||
LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/
|
||||
LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/
|
||||
LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/
|
||||
LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/
|
||||
|
||||
_LV_EVENT_LAST, /** Number of default events*/
|
||||
|
||||
|
||||
LV_EVENT_PREPROCESS = 0x80, /** This is a flag that can be set with an event so it's processed
|
||||
before the class default event processing */
|
||||
} lv_event_code_t;
|
||||
|
||||
typedef struct _lv_event_t {
|
||||
struct _lv_obj_t * target;
|
||||
struct _lv_obj_t * current_target;
|
||||
lv_event_code_t code;
|
||||
void * user_data;
|
||||
void * param;
|
||||
struct _lv_event_t * prev;
|
||||
uint8_t deleted : 1;
|
||||
uint8_t stop_processing : 1;
|
||||
uint8_t stop_bubbling : 1;
|
||||
} lv_event_t;
|
||||
|
||||
/**
|
||||
* @brief Event callback.
|
||||
* Events are used to notify the user of some action being taken on the object.
|
||||
* For details, see ::lv_event_t.
|
||||
*/
|
||||
typedef void (*lv_event_cb_t)(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* 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` an other 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`
|
||||
*/
|
||||
typedef struct {
|
||||
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*/
|
||||
} lv_hit_test_info_t;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
typedef struct {
|
||||
lv_cover_res_t res;
|
||||
const lv_area_t * area;
|
||||
} lv_cover_check_info_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_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event_code
|
||||
*/
|
||||
lv_res_t lv_event_send(struct _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_RES_OK: the target object was not deleted in the event; LV_RES_INV: it was deleted in the event_code
|
||||
*/
|
||||
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, 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 the target of the event_code
|
||||
*/
|
||||
struct _lv_obj_t * lv_event_get_target(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 "normal" target.
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the current target of the event_code
|
||||
*/
|
||||
struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the event code of an event
|
||||
* @param e pointer to the event descriptor
|
||||
* @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc)
|
||||
*/
|
||||
lv_event_code_t lv_event_get_code(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the parameter passed when the event was sent
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the parameter
|
||||
*/
|
||||
void * lv_event_get_param(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the user_data passed when the event was registered on the object
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the user_data
|
||||
*/
|
||||
void * lv_event_get_user_data(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Stop the event from bubbling.
|
||||
* This is only valid when called in the middle of an event processing chain.
|
||||
* @param e pointer to the event descriptor
|
||||
*/
|
||||
void lv_event_stop_bubbling(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Stop processing this event.
|
||||
* This is only valid when called in the middle of an event processing chain.
|
||||
* @param e pointer to the event descriptor
|
||||
*/
|
||||
void lv_event_stop_processing(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Register a new, custom event ID.
|
||||
* It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events
|
||||
* @return the new event id
|
||||
* @example
|
||||
* uint32_t LV_EVENT_MINE = 0;
|
||||
* ...
|
||||
* e = lv_event_register_id();
|
||||
* ...
|
||||
* lv_event_send(obj, LV_EVENT_MINE, &some_data);
|
||||
*/
|
||||
uint32_t lv_event_register_id(void);
|
||||
|
||||
/**
|
||||
* Nested events can be called and one of them might belong to an object that is being deleted.
|
||||
* Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV`
|
||||
* @param obj pointer to an object to mark as deleted
|
||||
*/
|
||||
void _lv_event_mark_deleted(struct _lv_obj_t * obj);
|
||||
|
||||
|
||||
/**
|
||||
* 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 and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events.
|
||||
* @param event_cb the new event function
|
||||
* @param user_data custom data data will be available in `event_cb`
|
||||
* @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc
|
||||
*/
|
||||
struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Remove an event handler function for an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_cb the event function to remove, or `NULL` to remove the firstly added event callback
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb);
|
||||
|
||||
/**
|
||||
* Remove an event handler function with a specific user_data from an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_cb the event function to remove, or `NULL` only `user_data` matters.
|
||||
* @param event_user_data the user_data specified in ::lv_obj_add_event_cb
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb,
|
||||
const void * event_user_data);
|
||||
|
||||
/**
|
||||
* DEPRECATED because doesn't work if multiple event handlers are added to an object.
|
||||
* Remove an event handler function for an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb)
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc);
|
||||
|
||||
/**
|
||||
* The user data of an event object event callback. Always the first match with `event_cb` will be returned.
|
||||
* @param obj pointer to an object
|
||||
* @param event_cb the event function
|
||||
* @return the user_data
|
||||
*/
|
||||
void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb);
|
||||
|
||||
/**
|
||||
* 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 part draw descriptor passed as parameter to `LV_EVENT_DRAW_PART_BEGIN/END`.
|
||||
* @param e pointer to an event
|
||||
* @return the part draw descriptor to hook the drawing or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(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_draw_ctx_t * lv_event_get_draw_ctx(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 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, lv_coord_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);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EVENT_H*/
|
||||
471
LVGL.Simulator/lvgl/src/core/lv_group.c
Normal file
471
LVGL.Simulator/lvgl/src/core/lv_group.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/**
|
||||
* @file lv_group.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lv_group.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../core/lv_obj.h"
|
||||
#include "../core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void 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
|
||||
**********************/
|
||||
static lv_group_t * default_group;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_group_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t));
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = _lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll));
|
||||
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->editing = 0;
|
||||
group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV;
|
||||
group->wrap = 1;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
group->user_data = NULL;
|
||||
#endif
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void lv_group_del(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*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(indev->group == group) {
|
||||
lv_indev_set_group(indev, NULL);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
_lv_ll_clear(&(group->obj_ll));
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group);
|
||||
lv_mem_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");
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
_LV_LL_READ(&group->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj) {
|
||||
LV_LOG_INFO("the object is already added to this group");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*If the object is already in a group and focused then refocus it*/
|
||||
lv_group_t * group_cur = lv_obj_get_group(obj);
|
||||
if(group_cur) {
|
||||
if(obj->spec_attr->group_p && *(obj->spec_attr->group_p->obj_focus) == obj) {
|
||||
lv_group_refocus(group_cur);
|
||||
|
||||
LV_LOG_INFO("changing object's group");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(*g1->obj_focus == obj1) lv_group_focus_obj(obj2);
|
||||
else if(*g1->obj_focus == 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_event_send(*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_mem_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)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*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_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
if(res != LV_RES_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_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_next(lv_group_t * group)
|
||||
{
|
||||
focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next);
|
||||
}
|
||||
|
||||
void lv_group_focus_prev(lv_group_t * group)
|
||||
{
|
||||
focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev);
|
||||
}
|
||||
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en)
|
||||
{
|
||||
if(en == false) group->frozen = 0;
|
||||
else group->frozen = 1;
|
||||
}
|
||||
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
|
||||
{
|
||||
lv_obj_t * act = lv_group_get_focused(group);
|
||||
if(act == NULL) return LV_RES_OK;
|
||||
|
||||
if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RES_OK;
|
||||
|
||||
return lv_event_send(act, LV_EVENT_KEY, &c);
|
||||
}
|
||||
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
|
||||
{
|
||||
group->focus_cb = focus_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
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_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_invalidate(focused);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)
|
||||
{
|
||||
group->refocus_policy = policy & 0x01;
|
||||
}
|
||||
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool lv_group_get_editing(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->editing ? true : false;
|
||||
}
|
||||
|
||||
bool lv_group_get_wrap(lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->wrap ? true : false;
|
||||
}
|
||||
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group)
|
||||
{
|
||||
return _lv_ll_get_len(&group->obj_ll);
|
||||
}
|
||||
/**********************
|
||||
* 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 void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *))
|
||||
{
|
||||
if(group->frozen) return;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj_sentinel == NULL) {
|
||||
obj_sentinel = obj_next;
|
||||
if(obj_sentinel == NULL) return; /*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;
|
||||
}
|
||||
|
||||
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; /*There's only one visible object and it's already focused*/
|
||||
|
||||
if(group->obj_focus) {
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an indev preferably with KEYPAD or ENCOEDR type 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_encoder = NULL;
|
||||
lv_indev_t * indev_group = NULL;
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev->group == g) {
|
||||
/*Prefer KEYPAD*/
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD) return indev;
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) indev_encoder = indev;
|
||||
indev_group = indev;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(indev_encoder) return indev_encoder;
|
||||
if(indev_group) return indev_group;
|
||||
|
||||
/*In lack of a better option use the first input device. (It can be NULL if there is no input device)*/
|
||||
return lv_indev_get_next(NULL);
|
||||
}
|
||||
|
||||
246
LVGL.Simulator/lvgl/src/core/lv_group.h
Normal file
246
LVGL.Simulator/lvgl/src/core/lv_group.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/**
|
||||
* @file lv_group.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_H
|
||||
#define LV_GROUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Predefined keys to control the focused object via lv_group_send(group, c)*/
|
||||
|
||||
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*/
|
||||
};
|
||||
typedef uint8_t lv_key_t;
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_group_t;
|
||||
|
||||
typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *);
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
typedef struct _lv_group_t {
|
||||
lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/
|
||||
struct _lv_obj_t ** obj_focus; /**< The object in focus*/
|
||||
|
||||
lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
|
||||
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.*/
|
||||
} lv_group_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
LV_GROUP_REFOCUS_POLICY_NEXT = 0,
|
||||
LV_GROUP_REFOCUS_POLICY_PREV = 1
|
||||
} lv_group_refocus_policy_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init. the group module
|
||||
* @remarks Internal function, do not call directly.
|
||||
*/
|
||||
void _lv_group_init(void);
|
||||
|
||||
/**
|
||||
* 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_del(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, struct _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 an other object
|
||||
*/
|
||||
void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2);
|
||||
|
||||
/**
|
||||
* Remove an object from its group
|
||||
* @param obj pointer to an object to remove
|
||||
*/
|
||||
void lv_group_remove_obj(struct _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(struct _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_res_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 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
|
||||
*/
|
||||
struct _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 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
|
||||
* @param en true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
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);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GROUP_H*/
|
||||
1154
LVGL.Simulator/lvgl/src/core/lv_indev.c
Normal file
1154
LVGL.Simulator/lvgl/src/core/lv_indev.c
Normal file
File diff suppressed because it is too large
Load Diff
176
LVGL.Simulator/lvgl/src/core/lv_indev.h
Normal file
176
LVGL.Simulator/lvgl/src/core/lv_indev.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file lv_indev.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_INDEV_H
|
||||
#define LV_INDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../hal/lv_hal_indev.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Called periodically to read the input devices
|
||||
* @param timer pointer to a timer to read
|
||||
*/
|
||||
void lv_indev_read_timer_cb(lv_timer_t * timer);
|
||||
|
||||
/**
|
||||
* Enable or disable one or all input devices (default enabled)
|
||||
* @param indev pointer to an input device or NULL to enable/disable all of them
|
||||
* @param en true to enable, false to disable
|
||||
*/
|
||||
void lv_indev_enable(lv_indev_t * indev, bool en);
|
||||
|
||||
/**
|
||||
* Get the currently processed input device. Can be used in action functions too.
|
||||
* @return pointer to the currently processed input device or NULL if no input device processing
|
||||
* right now
|
||||
*/
|
||||
lv_indev_t * lv_indev_get_act(void);
|
||||
|
||||
/**
|
||||
* Get the type of an input device
|
||||
* @param indev pointer to an input device
|
||||
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
|
||||
*/
|
||||
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Reset one or all input devices
|
||||
* @param indev pointer to an input device to reset or NULL to reset all of them
|
||||
* @param obj pointer to an object which triggers the reset.
|
||||
*/
|
||||
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Reset the long press state of an input device
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_reset_long_press(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param cur_obj pointer to an object to be used as cursor
|
||||
*/
|
||||
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj);
|
||||
|
||||
/**
|
||||
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
|
||||
* These points will be assigned to the buttons to press a specific point on the screen
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]);
|
||||
|
||||
/**
|
||||
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the result
|
||||
*/
|
||||
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Get the current gesture direct
|
||||
* @param indev pointer to an input device
|
||||
* @return current gesture direct
|
||||
*/
|
||||
lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @return the last pressed key (0 on error)
|
||||
*/
|
||||
uint32_t lv_indev_get_key(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return LV_DIR_NONE: no scrolling now
|
||||
* LV_DIR_HOR/VER
|
||||
*/
|
||||
lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return pointer to the currently scrolled object or NULL if no scrolling by this indev
|
||||
*/
|
||||
lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the types.pointer.vector
|
||||
*/
|
||||
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Do nothing until the next release
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_wait_release(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Gets a pointer to the currently active object in the currently processed input device.
|
||||
* @return pointer to currently active object or NULL if no active object
|
||||
*/
|
||||
lv_obj_t * lv_indev_get_obj_act(void);
|
||||
|
||||
/**
|
||||
* Get a pointer to the indev read timer to
|
||||
* modify its parameters with `lv_timer_...` functions.
|
||||
* @param indev pointer to an input device
|
||||
* @return pointer to the indev read refresher timer. (NULL on error)
|
||||
*/
|
||||
lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev);
|
||||
|
||||
/**
|
||||
* Search the most top, clickable object by a point
|
||||
* @param obj pointer to a start object, typically the screen
|
||||
* @param point pointer to a point for searching the most top child
|
||||
* @return pointer to the found object or NULL if there was no suitable object
|
||||
*/
|
||||
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_INDEV_H*/
|
||||
651
LVGL.Simulator/lvgl/src/core/lv_indev_scroll.c
Normal file
651
LVGL.Simulator/lvgl/src/core/lv_indev_scroll.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/**
|
||||
* @file lv_indev_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_indev.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ELASTIC_SLOWNESS_FACTOR 4 /*Scrolling on elastic parts are slower by this factor*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc);
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y);
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
/*If there is no scroll object yet try to find one*/
|
||||
if(scroll_obj == NULL) {
|
||||
proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x;
|
||||
proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y;
|
||||
|
||||
scroll_obj = find_scroll_obj(proc);
|
||||
if(scroll_obj == NULL) return;
|
||||
|
||||
init_scroll_limits(proc);
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(proc->reset_query) return;
|
||||
}
|
||||
|
||||
/*Set new position or scroll if the vector is not zero*/
|
||||
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
|
||||
lv_coord_t diff_x = 0;
|
||||
lv_coord_t diff_y = 0;
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR);
|
||||
}
|
||||
else {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER);
|
||||
}
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
|
||||
|
||||
/*Respect the scroll limit area*/
|
||||
scroll_limit_diff(proc, &diff_x, &diff_y);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, diff_x, diff_y, LV_ANIM_OFF);
|
||||
proc->types.pointer.scroll_sum.x += diff_x;
|
||||
proc->types.pointer.scroll_sum.y += diff_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
if(scroll_obj == NULL) return;
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_NONE) return;
|
||||
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_MOMENTUM) == false) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t align_x = lv_obj_get_scroll_snap_x(scroll_obj);
|
||||
lv_scroll_snap_t align_y = lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_VER) {
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.y =
|
||||
proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb,
|
||||
LV_DIR_VER);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_y = scroll_throw_predict_y(proc);
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
scroll_limit_diff(proc, NULL, &diff_y);
|
||||
lv_coord_t y = find_snap_point_y(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_y);
|
||||
lv_obj_scroll_by(scroll_obj, 0, diff_y + y, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
else if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.x =
|
||||
proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl, sr,
|
||||
LV_DIR_HOR);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_x = scroll_throw_predict_x(proc);
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
scroll_limit_diff(proc, &diff_x, NULL);
|
||||
lv_coord_t x = find_snap_point_x(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_x);
|
||||
lv_obj_scroll_by(scroll_obj, x + diff_x, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
|
||||
/*Check if the scroll has finished*/
|
||||
if(proc->types.pointer.scroll_throw_vect.x == 0 && proc->types.pointer.scroll_throw_vect.y == 0) {
|
||||
/*Revert if scrolled in*/
|
||||
/*If vertically scrollable and not controlled by snap*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
if(st > 0 || sb > 0) {
|
||||
if(st < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, st, LV_ANIM_ON);
|
||||
}
|
||||
else if(sb < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, -sb, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*If horizontally scrollable and not controlled by snap*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
if(sl > 0 || sr > 0) {
|
||||
if(sl < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, sl, 0, LV_ANIM_ON);
|
||||
}
|
||||
else if(sr < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, -sr, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act);
|
||||
if(proc->reset_query) return;
|
||||
|
||||
proc->types.pointer.scroll_dir = LV_DIR_NONE;
|
||||
proc->types.pointer.scroll_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict where would a scroll throw end
|
||||
* @param indev pointer to an input device
|
||||
* @param dir `LV_DIR_VER` or `LV_DIR_HOR`
|
||||
* @return the difference compared to the current position when the throw would be finished
|
||||
*/
|
||||
lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir)
|
||||
{
|
||||
if(indev == NULL) return 0;
|
||||
lv_coord_t v;
|
||||
switch(dir) {
|
||||
case LV_DIR_VER:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.y;
|
||||
break;
|
||||
case LV_DIR_HOR:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.x;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv_coord_t scroll_throw = indev->driver->scroll_throw;
|
||||
lv_coord_t sum = 0;
|
||||
while(v) {
|
||||
sum += v;
|
||||
v = v * (100 - scroll_throw) / 100;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p)
|
||||
{
|
||||
p->x = find_snap_point_x(obj, obj->coords.x1, obj->coords.x2, 0);
|
||||
p->y = find_snap_point_y(obj, obj->coords.y1, obj->coords.y2, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj_candidate = NULL;
|
||||
lv_dir_t dir_candidate = LV_DIR_NONE;
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_limit = indev_act->driver->scroll_limit;
|
||||
|
||||
/*Go until find a scrollable object in the current direction
|
||||
*More precisely:
|
||||
* 1. Check the pressed object and all of its ancestors and try to find an object which is scrollable
|
||||
* 2. Scrollable means it has some content out of its area
|
||||
* 3. If an object can be scrolled into the current direction then use it ("real match"")
|
||||
* 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect)
|
||||
* 5. Use the last candidate. Always the "deepest" parent or the object from point 3*/
|
||||
lv_obj_t * obj_act = proc->types.pointer.act_obj;
|
||||
|
||||
/*Decide if it's a horizontal or vertical scroll*/
|
||||
bool hor_en = false;
|
||||
bool ver_en = false;
|
||||
if(LV_ABS(proc->types.pointer.scroll_sum.x) > LV_ABS(proc->types.pointer.scroll_sum.y)) {
|
||||
hor_en = true;
|
||||
}
|
||||
else {
|
||||
ver_en = true;
|
||||
}
|
||||
|
||||
while(obj_act) {
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLLABLE) == false) {
|
||||
/*If this object don't want to chain the scroll to the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_HOR) == false && hor_en) break;
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_VER) == false && ver_en) break;
|
||||
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Consider both up-down or left/right scrollable according to the current direction*/
|
||||
bool up_en = ver_en;
|
||||
bool down_en = ver_en;
|
||||
bool left_en = hor_en;
|
||||
bool right_en = hor_en;
|
||||
|
||||
/*The object might have disabled some directions.*/
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(obj_act);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0) left_en = false;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0) right_en = false;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0) up_en = false;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0) down_en = false;
|
||||
|
||||
/*The object is scrollable to a direction if its content overflow in that direction.*/
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj_act);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj_act);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj_act);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj_act);
|
||||
|
||||
/*If this object is scrollable into the current scroll direction then save it as a candidate.
|
||||
*It's important only to be scrollable on the current axis (hor/ver) because if the scroll
|
||||
*is propagated to this object it can show at least elastic scroll effect.
|
||||
*But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate)*/
|
||||
if((st > 0 || sb > 0) &&
|
||||
((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_VER;
|
||||
}
|
||||
|
||||
if((sl > 0 || sr > 0) &&
|
||||
((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_HOR;
|
||||
}
|
||||
|
||||
if(st <= 0) up_en = false;
|
||||
if(sb <= 0) down_en = false;
|
||||
if(sl <= 0) left_en = false;
|
||||
if(sr <= 0) right_en = false;
|
||||
|
||||
/*If the object really can be scrolled into the current direction the use it.*/
|
||||
if((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) ||
|
||||
(up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) {
|
||||
proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER;
|
||||
break;
|
||||
}
|
||||
|
||||
/*If this object don't want to chain the scroll to the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_HOR) == false && hor_en) break;
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_VER) == false && ver_en) break;
|
||||
|
||||
/*Try the parent*/
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
}
|
||||
|
||||
/*Use the last candidate*/
|
||||
if(obj_candidate) {
|
||||
proc->types.pointer.scroll_dir = dir_candidate;
|
||||
proc->types.pointer.scroll_obj = obj_candidate;
|
||||
proc->types.pointer.scroll_sum.x = 0;
|
||||
proc->types.pointer.scroll_sum.y = 0;
|
||||
}
|
||||
|
||||
return obj_candidate;
|
||||
}
|
||||
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj = proc->types.pointer.scroll_obj;
|
||||
/*If there no STOP allow scrolling anywhere*/
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ONE) == false) {
|
||||
lv_area_set(&proc->types.pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX);
|
||||
}
|
||||
/*With STOP limit the scrolling to the perv and next snap point*/
|
||||
else {
|
||||
switch(lv_obj_get_scroll_snap_y(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(lv_obj_get_scroll_snap_x(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*Allow scrolling on the edges. It will be reverted to the edge due to snapping anyway*/
|
||||
if(proc->types.pointer.scroll_area.x1 == 0) proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.x2 == 0) proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
if(proc->types.pointer.scroll_area.y1 == 0) proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.y2 == 0) proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful the get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_x(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t x_child = 0;
|
||||
lv_coord_t x_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
x_child = child->coords.x1;
|
||||
x_parent = obj->coords.x1 + pad_left;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
x_child = child->coords.x2;
|
||||
x_parent = obj->coords.x2 - pad_right;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
x_child = child->coords.x1 + lv_area_get_width(&child->coords) / 2;
|
||||
x_parent = obj->coords.x1 + pad_left + (lv_area_get_width(&obj->coords) - pad_left - pad_right) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
x_child += ofs;
|
||||
if(x_child >= min && x_child <= max) {
|
||||
lv_coord_t x = x_child - x_parent;
|
||||
if(LV_ABS(x) < LV_ABS(dist)) dist = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful to get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_y(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t y_child = 0;
|
||||
lv_coord_t y_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
y_child = child->coords.y1;
|
||||
y_parent = obj->coords.y1 + pad_top;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
y_child = child->coords.y2;
|
||||
y_parent = obj->coords.y2 - pad_bottom;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
y_child = child->coords.y1 + lv_area_get_height(&child->coords) / 2;
|
||||
y_parent = obj->coords.y1 + pad_top + (lv_area_get_height(&obj->coords) - pad_top - pad_bottom) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
y_child += ofs;
|
||||
if(y_child >= min && y_child <= max) {
|
||||
lv_coord_t y = y_child - y_parent;
|
||||
if(LV_ABS(y) < LV_ABS(dist)) dist = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y)
|
||||
{
|
||||
if(diff_y) {
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y > proc->types.pointer.scroll_area.y2) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y2 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(diff_x) {
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x < proc->types.pointer.scroll_area.x1) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x1 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x > proc->types.pointer.scroll_area.x2) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x2 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t y = proc->types.pointer.scroll_throw_vect.y;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(y) {
|
||||
move += y;
|
||||
y = y * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t x = proc->types.pointer.scroll_throw_vect.x;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(x) {
|
||||
move += x;
|
||||
x = x * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir)
|
||||
{
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) {
|
||||
/*If there is snapping in the current direction don't use the elastic factor because
|
||||
*it's natural that the first and last items are scrolled (snapped) in.*/
|
||||
lv_scroll_snap_t snap;
|
||||
snap = dir == LV_DIR_HOR ? lv_obj_get_scroll_snap_x(scroll_obj) : lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
lv_obj_t * act_obj = lv_indev_get_obj_act();
|
||||
lv_coord_t snap_point = 0;
|
||||
lv_coord_t act_obj_point = 0;
|
||||
|
||||
if(dir == LV_DIR_HOR) {
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_left + (lv_area_get_width(&scroll_obj->coords) - pad_left - pad_right) / 2 + scroll_obj->coords.x1;
|
||||
act_obj_point = lv_area_get_width(&act_obj->coords) / 2 + act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.x1 + pad_left;
|
||||
act_obj_point = act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.x2 - pad_right;
|
||||
act_obj_point = act_obj->coords.x2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_top + (lv_area_get_height(&scroll_obj->coords) - pad_top - pad_bottom) / 2 + scroll_obj->coords.y1;
|
||||
act_obj_point = lv_area_get_height(&act_obj->coords) / 2 + act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.y1 + pad_top;
|
||||
act_obj_point = act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.y2 - pad_bottom;
|
||||
act_obj_point = act_obj->coords.y2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(scroll_end < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point > snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
else if(scroll_start < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point < snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Scroll back to the boundary if required*/
|
||||
if(scroll_end + diff < 0) diff = - scroll_end;
|
||||
if(scroll_start - diff < 0) diff = scroll_start;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
65
LVGL.Simulator/lvgl/src/core/lv_indev_scroll.h
Normal file
65
LVGL.Simulator/lvgl/src/core/lv_indev_scroll.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file lv_indev_scroll.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_INDEV_SCROLL_H
|
||||
#define LV_INDEV_SCROLL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle scrolling. Called by LVGL during input device processing
|
||||
* @param proc pointer to an input device's proc field
|
||||
*/
|
||||
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc);
|
||||
|
||||
/**
|
||||
* Handle throwing after scrolling. Called by LVGL during input device processing
|
||||
* @param proc pointer to an input device's proc field
|
||||
*/
|
||||
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc);
|
||||
|
||||
/**
|
||||
* Predict where would a scroll throw end
|
||||
* @param indev pointer to an input device
|
||||
* @param dir ` LV_DIR_VER` or `LV_DIR_HOR`
|
||||
* @return the difference compared to the current position when the throw would be finished
|
||||
*/
|
||||
lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir);
|
||||
|
||||
/**
|
||||
* Get the distance of the nearest snap point
|
||||
* @param obj the object on which snap points should be found
|
||||
* @param p save the distance of the found snap point there
|
||||
*/
|
||||
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_INDEV_SCROLL_H*/
|
||||
955
LVGL.Simulator/lvgl/src/core/lv_obj.c
Normal file
955
LVGL.Simulator/lvgl/src/core/lv_obj.c
Normal file
@@ -0,0 +1,955 @@
|
||||
/**
|
||||
* @file lv_obj.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_refr.h"
|
||||
#include "lv_group.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_theme.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_async.h"
|
||||
#include "../misc/lv_fs.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../hal/lv_hal.h"
|
||||
#include "../extra/lv_extra.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
#include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "../gpu/lv_gpu_nxp_pxp.h"
|
||||
#include "../gpu/lv_gpu_nxp_pxp_osa.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
#define LV_OBJ_DEF_WIDTH (LV_DPX(100))
|
||||
#define LV_OBJ_DEF_HEIGHT (LV_DPX(50))
|
||||
#define STYLE_TRANSITION_MAX 32
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_draw(lv_event_t * e);
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx);
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc);
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool lv_initialized = false;
|
||||
const lv_obj_class_t lv_obj_class = {
|
||||
.constructor_cb = lv_obj_constructor,
|
||||
.destructor_cb = lv_obj_destructor,
|
||||
.event_cb = lv_obj_event,
|
||||
.width_def = LV_DPI_DEF,
|
||||
.height_def = LV_DPI_DEF,
|
||||
.editable = LV_OBJ_CLASS_EDITABLE_FALSE,
|
||||
.group_def = LV_OBJ_CLASS_GROUP_DEF_FALSE,
|
||||
.instance_size = (sizeof(lv_obj_t)),
|
||||
.base_class = NULL,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_is_initialized(void)
|
||||
{
|
||||
return lv_initialized;
|
||||
}
|
||||
|
||||
void lv_init(void)
|
||||
{
|
||||
/*Do nothing if already initialized*/
|
||||
if(lv_initialized) {
|
||||
LV_LOG_WARN("lv_init: already inited");
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("begin");
|
||||
|
||||
/*Initialize the misc modules*/
|
||||
lv_mem_init();
|
||||
|
||||
_lv_timer_core_init();
|
||||
|
||||
_lv_fs_init();
|
||||
|
||||
_lv_anim_core_init();
|
||||
|
||||
_lv_group_init();
|
||||
|
||||
lv_draw_init();
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
/*Initialize DMA2D GPU*/
|
||||
lv_draw_stm32_dma2d_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
if(lv_gpu_nxp_pxp_init(&pxp_default_cfg) != LV_RES_OK) {
|
||||
LV_LOG_ERROR("PXP init error. STOP.\n");
|
||||
for(; ;) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
_lv_obj_style_init();
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t));
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t));
|
||||
|
||||
/*Initialize the screen refresh system*/
|
||||
_lv_refr_init();
|
||||
|
||||
_lv_img_decoder_init();
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
|
||||
#endif
|
||||
/*Test if the IDE has UTF-8 encoding*/
|
||||
char * txt = "Á";
|
||||
|
||||
uint8_t * txt_u8 = (uint8_t *)txt;
|
||||
if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) {
|
||||
LV_LOG_WARN("The strings have no UTF-8 encoding. Non-ASCII characters won't be displayed.");
|
||||
}
|
||||
|
||||
uint32_t endianess_test = 0x11223344;
|
||||
uint8_t * endianess_test_p = (uint8_t *) &endianess_test;
|
||||
bool big_endian = endianess_test_p[0] == 0x11 ? true : false;
|
||||
|
||||
if(big_endian) {
|
||||
LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1,
|
||||
"It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h");
|
||||
}
|
||||
else {
|
||||
LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0,
|
||||
"It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h");
|
||||
}
|
||||
|
||||
#if LV_USE_ASSERT_MEM_INTEGRITY
|
||||
LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
#if LV_USE_ASSERT_OBJ
|
||||
LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
LV_LOG_WARN("Style sanity checks are enabled that uses more RAM");
|
||||
#endif
|
||||
|
||||
#if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE
|
||||
LV_LOG_WARN("Log level is set to 'Trace' which makes LVGL much slower");
|
||||
#endif
|
||||
|
||||
lv_extra_init();
|
||||
|
||||
lv_initialized = true;
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
#if LV_ENABLE_GC || !LV_MEM_CUSTOM
|
||||
|
||||
void lv_deinit(void)
|
||||
{
|
||||
_lv_gc_clear_roots();
|
||||
|
||||
lv_disp_set_default(NULL);
|
||||
lv_mem_deinit();
|
||||
lv_initialized = false;
|
||||
|
||||
LV_LOG_INFO("lv_deinit done");
|
||||
|
||||
#if LV_USE_LOG
|
||||
lv_log_register_print_cb(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*-----------------
|
||||
* Attribute set
|
||||
*----------------*/
|
||||
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) lv_obj_invalidate(obj);
|
||||
|
||||
obj->flags |= f;
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
obj->flags &= (~f);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
if(lv_obj_is_layout_positioned(obj)) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state | state;
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state & (~state);
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) == f ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) ? true : false;
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_get_state(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state;
|
||||
}
|
||||
|
||||
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state & state ? true : false;
|
||||
}
|
||||
|
||||
void * lv_obj_get_group(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr) return obj->spec_attr->group_p;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
* OTHER FUNCTIONS
|
||||
*------------------*/
|
||||
|
||||
void lv_obj_allocate_spec_attr(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) {
|
||||
static uint32_t x = 0;
|
||||
x++;
|
||||
obj->spec_attr = lv_mem_alloc(sizeof(_lv_obj_spec_attr_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr);
|
||||
if(obj->spec_attr == NULL) return;
|
||||
|
||||
lv_memset_00(obj->spec_attr, sizeof(_lv_obj_spec_attr_t));
|
||||
|
||||
obj->spec_attr->scroll_dir = LV_DIR_ALL;
|
||||
obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
if(obj == NULL) return false;
|
||||
return obj->class_p == class_p ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
const lv_obj_class_t * obj_class = obj->class_p;
|
||||
while(obj_class) {
|
||||
if(obj_class == class_p) return true;
|
||||
obj_class = obj_class->base_class;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj)
|
||||
{
|
||||
return obj->class_p;
|
||||
}
|
||||
|
||||
bool lv_obj_is_valid(const lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) return true;
|
||||
bool found = obj_valid_child(disp->screens[i], obj);
|
||||
if(found) return true;
|
||||
}
|
||||
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_obj_t * parent = obj->parent;
|
||||
if(parent) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(parent);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(parent);
|
||||
|
||||
obj->coords.y1 = parent->coords.y1 + lv_obj_get_style_pad_top(parent, LV_PART_MAIN) - st;
|
||||
obj->coords.y2 = obj->coords.y1 - 1;
|
||||
obj->coords.x1 = parent->coords.x1 + lv_obj_get_style_pad_left(parent, LV_PART_MAIN) - sl;
|
||||
obj->coords.x2 = obj->coords.x1 - 1;
|
||||
}
|
||||
|
||||
/*Set attributes*/
|
||||
obj->flags = LV_OBJ_FLAG_CLICKABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SNAPPABLE;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_PRESS_LOCK;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_SCROLL_CHAIN;
|
||||
obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLLABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_WITH_ARROW;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
_lv_event_mark_deleted(obj);
|
||||
|
||||
/*Remove all style*/
|
||||
lv_obj_enable_style_refresh(false); /*No need to refresh the style because the object will be deleted*/
|
||||
lv_obj_remove_style_all(obj);
|
||||
lv_obj_enable_style_refresh(true);
|
||||
|
||||
/*Remove the animations from this object*/
|
||||
lv_anim_del(obj, NULL);
|
||||
|
||||
/*Delete from the group*/
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
if(group) lv_group_remove_obj(obj);
|
||||
|
||||
if(obj->spec_attr) {
|
||||
if(obj->spec_attr->children) {
|
||||
lv_mem_free(obj->spec_attr->children);
|
||||
obj->spec_attr->children = NULL;
|
||||
}
|
||||
if(obj->spec_attr->event_dsc) {
|
||||
lv_mem_free(obj->spec_attr->event_dsc);
|
||||
obj->spec_attr->event_dsc = NULL;
|
||||
}
|
||||
|
||||
lv_mem_free(obj->spec_attr);
|
||||
obj->spec_attr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_obj_draw(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res == LV_COVER_RES_MASKED) return;
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
info->res = LV_COVER_RES_MASKED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/
|
||||
lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
if(_lv_area_is_in(info->area, &coords, r) == false) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_blend_mode(obj, LV_PART_MAIN) != LV_BLEND_MODE_NORMAL) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(lv_obj_get_style_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||
lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
/*If the border is drawn later disable loading its properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
draw_dsc.border_post = 1;
|
||||
}
|
||||
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*With clip corner enabled draw the bg img separately to make it clipped*/
|
||||
bool clip_corner = (lv_obj_get_style_clip_corner(obj, LV_PART_MAIN) && draw_dsc.radius != 0) ? true : false;
|
||||
const void * bg_img_src = draw_dsc.bg_img_src;
|
||||
if(clip_corner) {
|
||||
draw_dsc.bg_img_src = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(clip_corner) {
|
||||
lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t));
|
||||
lv_draw_mask_radius_init(mp, &obj->coords, draw_dsc.radius, false);
|
||||
/*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/
|
||||
lv_draw_mask_add(mp, obj + 8);
|
||||
|
||||
if(bg_img_src) {
|
||||
draw_dsc.bg_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;
|
||||
draw_dsc.bg_img_src = bg_img_src;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_POST) {
|
||||
lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
|
||||
draw_scrollbar(obj, draw_ctx);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
||||
if(param) {
|
||||
lv_draw_mask_free_param(param);
|
||||
lv_mem_buf_release(param);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*If the border is drawn later disable loading other properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
draw_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.bg_img_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.outline_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.shadow_opa = LV_OPA_TRANSP;
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &coords);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc);
|
||||
if(sb_res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, draw_ctx);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_SCROLLBAR;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.part = LV_PART_SCROLLBAR;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) {
|
||||
part_dsc.draw_area = &hor_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &hor_area);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
if(lv_area_get_size(&ver_area) > 0) {
|
||||
part_dsc.draw_area = &ver_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
part_dsc.draw_area = &ver_area;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc, &ver_area);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the draw descriptor for the scrollbar
|
||||
* @param obj pointer to an object
|
||||
* @param dsc the draw descriptor to initialize
|
||||
* @return LV_RES_OK: the scrollbar is visible; LV_RES_INV: the scrollbar is not visible
|
||||
*/
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
lv_draw_rect_dsc_init(dsc);
|
||||
dsc->bg_opa = lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->bg_opa > LV_OPA_MIN) {
|
||||
dsc->bg_color = lv_obj_get_style_bg_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
|
||||
dsc->border_opa = lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_opa > LV_OPA_MIN) {
|
||||
dsc->border_width = lv_obj_get_style_border_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_width > 0) {
|
||||
dsc->border_color = lv_obj_get_style_border_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->border_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_opa > LV_OPA_MIN) {
|
||||
dsc->shadow_width = lv_obj_get_style_shadow_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_width > 0) {
|
||||
dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, LV_PART_SCROLLBAR);
|
||||
dsc->shadow_color = lv_obj_get_style_shadow_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
dsc->bg_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->border_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->shadow_opa = (dsc->bg_opa * opa) >> 8;
|
||||
}
|
||||
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP) {
|
||||
dsc->radius = lv_obj_get_style_radius(obj, LV_PART_SCROLLBAR);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
#else
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) return LV_RES_OK;
|
||||
else return LV_RES_INV;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||
if(code == LV_EVENT_PRESSED) {
|
||||
lv_obj_add_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_RELEASED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
void * param = lv_event_get_param(e);
|
||||
/*Go the checked state if enabled*/
|
||||
if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
else lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_PRESS_LOST) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_STYLE_CHANGED) {
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(uint32_t i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_KEY) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||
lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
/*With Enter LV_EVENT_RELEASED will send VALUE_CHANGE event*/
|
||||
if(c != LV_KEY_ENTER) {
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW) && !lv_obj_is_editable(obj)) {
|
||||
/*scroll by keypad or encoder*/
|
||||
lv_anim_enable_t anim_enable = LV_ANIM_OFF;
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_DOWN) {
|
||||
/*use scroll_to_x/y functions to enforce scroll limits*/
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_UP) {
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_RIGHT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) + lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) - lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_FOCUSED) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS)) {
|
||||
lv_obj_scroll_to_view_recursive(obj, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
bool editing = false;
|
||||
editing = lv_group_get_editing(lv_obj_get_group(obj));
|
||||
lv_state_t state = LV_STATE_FOCUSED;
|
||||
|
||||
/* Use the indev for then indev handler.
|
||||
* But if the obj was focused manually it returns NULL so try to
|
||||
* use the indev from the event*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev == NULL) indev = lv_event_get_indev(e);
|
||||
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD || indev_type == LV_INDEV_TYPE_ENCODER) state |= LV_STATE_FOCUS_KEY;
|
||||
if(editing) {
|
||||
state |= LV_STATE_EDITED;
|
||||
lv_obj_add_state(obj, state);
|
||||
}
|
||||
else {
|
||||
lv_obj_add_state(obj, state);
|
||||
lv_obj_clear_state(obj, LV_STATE_EDITED);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_BEGIN) {
|
||||
lv_obj_add_state(obj, LV_STATE_SCROLLED);
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_END) {
|
||||
lv_obj_clear_state(obj, LV_STATE_SCROLLED);
|
||||
if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DEFOCUSED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY);
|
||||
}
|
||||
else if(code == LV_EVENT_SIZE_CHANGED) {
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_CHILD_CHANGED) {
|
||||
lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_MAIN);
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align || w == LV_SIZE_CONTENT || h == LV_SIZE_CONTENT) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t * s = lv_event_get_param(e);
|
||||
lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN);
|
||||
*s = LV_MAX(*s, d);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) {
|
||||
lv_obj_draw(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state (fully overwrite) of an object.
|
||||
* If specified in the styles, transition animations will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the new state
|
||||
*/
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state)
|
||||
{
|
||||
if(obj->state == new_state) return;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t prev_state = obj->state;
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_style_state_cmp_t cmp_res = _lv_obj_style_state_compare(obj, prev_state, new_state);
|
||||
/*If there is no difference in styles there is nothing else to do*/
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_SAME) return;
|
||||
|
||||
_lv_obj_style_transition_dsc_t * ts = lv_mem_buf_get(sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
lv_memset_00(ts, sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
uint32_t tsi = 0;
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt && tsi < STYLE_TRANSITION_MAX; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if(state_act & (~new_state)) continue; /*Skip unrelated styles*/
|
||||
if(obj_style->is_trans) continue;
|
||||
|
||||
lv_style_value_t v;
|
||||
if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) == false) continue;
|
||||
const lv_style_transition_dsc_t * tr = v.ptr;
|
||||
|
||||
/*Add the props to the set if not added yet or added but with smaller weight*/
|
||||
uint32_t j;
|
||||
for(j = 0; tr->props[j] != 0 && tsi < STYLE_TRANSITION_MAX; j++) {
|
||||
uint32_t t;
|
||||
for(t = 0; t < tsi; t++) {
|
||||
lv_style_selector_t selector = ts[t].selector;
|
||||
lv_state_t state_ts = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part_ts = lv_obj_style_get_selector_part(selector);
|
||||
if(ts[t].prop == tr->props[j] && part_ts == part_act && state_ts >= state_act) break;
|
||||
}
|
||||
|
||||
/*If not found add it*/
|
||||
if(t == tsi) {
|
||||
ts[tsi].time = tr->time;
|
||||
ts[tsi].delay = tr->delay;
|
||||
ts[tsi].path_cb = tr->path_xcb;
|
||||
ts[tsi].prop = tr->props[j];
|
||||
#if LV_USE_USER_DATA
|
||||
ts[tsi].user_data = tr->user_data;
|
||||
#endif
|
||||
ts[tsi].selector = obj_style->selector;
|
||||
tsi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < tsi; i++) {
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(ts[i].selector);
|
||||
_lv_obj_style_create_transition(obj, part_act, prev_state, new_state, &ts[i]);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(ts);
|
||||
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_REDRAW) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD) {
|
||||
lv_obj_invalidate(obj);
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find)
|
||||
{
|
||||
/*Check all children of `parent`*/
|
||||
uint32_t child_cnt = 0;
|
||||
if(parent->spec_attr) child_cnt = parent->spec_attr->child_cnt;
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = parent->spec_attr->children[i];
|
||||
if(child == obj_to_find) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*Check the children*/
|
||||
bool found = obj_valid_child(child, obj_to_find);
|
||||
if(found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
408
LVGL.Simulator/lvgl/src/core/lv_obj.h
Normal file
408
LVGL.Simulator/lvgl/src/core/lv_obj.h
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* @file lv_obj.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_H
|
||||
#define LV_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../hal/lv_hal.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
|
||||
/**
|
||||
* 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*/
|
||||
};
|
||||
|
||||
typedef uint16_t lv_state_t;
|
||||
|
||||
/**
|
||||
* The possible parts of widgets.
|
||||
* The parts can be considered as the internal building block of the widgets.
|
||||
* E.g. slider = background + indicator + knob
|
||||
* 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_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/
|
||||
LV_PART_CURSOR = 0x070000, /**< 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*/
|
||||
};
|
||||
|
||||
typedef uint32_t lv_part_t;
|
||||
|
||||
/**
|
||||
* On/Off features controlling the object's behavior.
|
||||
* OR-ed values are possible
|
||||
*/
|
||||
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 position-able by the layouts*/
|
||||
LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
|
||||
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/
|
||||
|
||||
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*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef uint32_t lv_obj_flag_t;
|
||||
|
||||
/**
|
||||
* `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class`
|
||||
* Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END`
|
||||
*/
|
||||
typedef enum {
|
||||
LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/
|
||||
LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/
|
||||
LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/
|
||||
} lv_obj_draw_part_type_t;
|
||||
|
||||
#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_event.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/**
|
||||
* Make the base object's class publicly available.
|
||||
*/
|
||||
extern const lv_obj_class_t lv_obj_class;
|
||||
|
||||
/**
|
||||
* Special, rarely used attributes.
|
||||
* They are allocated automatically if any elements is set.
|
||||
*/
|
||||
typedef struct {
|
||||
struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/
|
||||
uint32_t child_cnt; /**< Number of children*/
|
||||
lv_group_t * group_p;
|
||||
|
||||
struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/
|
||||
lv_point_t scroll; /**< The current X/Y scroll offset*/
|
||||
|
||||
lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/
|
||||
lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/
|
||||
|
||||
lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/
|
||||
lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/
|
||||
lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/
|
||||
lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/
|
||||
uint8_t event_dsc_cnt; /**< Number of event callbacks stored in `event_dsc` array*/
|
||||
} _lv_obj_spec_attr_t;
|
||||
|
||||
typedef struct _lv_obj_t {
|
||||
const lv_obj_class_t * class_p;
|
||||
struct _lv_obj_t * parent;
|
||||
_lv_obj_spec_attr_t * spec_attr;
|
||||
_lv_obj_style_t * styles;
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
lv_area_t coords;
|
||||
lv_obj_flag_t flags;
|
||||
lv_state_t state;
|
||||
uint16_t layout_inv : 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;
|
||||
} lv_obj_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize LVGL library.
|
||||
* Should be called before any other LVGL related function.
|
||||
*/
|
||||
void lv_init(void);
|
||||
|
||||
#if LV_ENABLE_GC || !LV_MEM_CUSTOM
|
||||
|
||||
/**
|
||||
* Deinit the 'lv' library
|
||||
* Currently only implemented when not using custom allocators, or GC is enabled.
|
||||
*/
|
||||
void lv_deinit(void);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns whether the 'lv' library is currently initialized
|
||||
*/
|
||||
bool lv_is_initialized(void);
|
||||
|
||||
/**
|
||||
* 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 R-ed values from `lv_obj_flag_t` to set.
|
||||
*/
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Clear 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_clear_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
|
||||
/**
|
||||
* 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_clear_state(lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Set the user_data field of the object
|
||||
* @param obj pointer to an object
|
||||
* @param user_data pointer to the new user_data.
|
||||
*/
|
||||
#if LV_USE_USER_DATA
|
||||
static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data)
|
||||
{
|
||||
obj->user_data = user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* 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 lest one flag 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
|
||||
*/
|
||||
void * 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
|
||||
*/
|
||||
#if LV_USE_USER_DATA
|
||||
static inline void * lv_obj_get_user_data(lv_obj_t * obj)
|
||||
{
|
||||
return obj->user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
|
||||
* considering the DPI of the `obj`'s display.
|
||||
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
|
||||
* DPI of the display.
|
||||
* @param obj an object whose display's dpi should be considered
|
||||
* @param n the number of pixels to scale
|
||||
* @return `n x current_dpi/160`
|
||||
*/
|
||||
static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n)
|
||||
{
|
||||
return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* 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*/
|
||||
202
LVGL.Simulator/lvgl/src/core/lv_obj_class.c
Normal file
202
LVGL.Simulator/lvgl/src/core/lv_obj_class.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file lv_obj_class.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_construct(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_mem_alloc(s);
|
||||
if(obj == NULL) return NULL;
|
||||
lv_memset_00(obj, s);
|
||||
obj->class_p = class_p;
|
||||
obj->parent = parent;
|
||||
|
||||
/*Create a screen*/
|
||||
if(parent == NULL) {
|
||||
LV_TRACE_OBJ_CREATE("creating a screen");
|
||||
lv_disp_t * disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("No display created yet. No place to assign the new screen");
|
||||
lv_mem_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(disp->screens == NULL) {
|
||||
disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
disp->screens[0] = obj;
|
||||
disp->screen_cnt = 1;
|
||||
}
|
||||
else {
|
||||
disp->screen_cnt++;
|
||||
disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
|
||||
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_disp_get_hor_res(NULL) - 1;
|
||||
obj->coords.y2 = lv_disp_get_ver_res(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);
|
||||
}
|
||||
|
||||
if(parent->spec_attr->children == NULL) {
|
||||
parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
parent->spec_attr->children[0] = obj;
|
||||
parent->spec_attr->child_cnt = 1;
|
||||
}
|
||||
else {
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_mem_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)
|
||||
{
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
lv_obj_enable_style_refresh(false);
|
||||
|
||||
lv_theme_apply(obj);
|
||||
lv_obj_construct(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_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(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 ? true : false;
|
||||
}
|
||||
|
||||
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 ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_construct(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * original_class_p = obj->class_p;
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*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(obj);
|
||||
}
|
||||
|
||||
/*Restore the original class*/
|
||||
obj->class_p = original_class_p;
|
||||
|
||||
if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->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;
|
||||
}
|
||||
94
LVGL.Simulator/lvgl/src/core/lv_obj_class.h
Normal file
94
LVGL.Simulator/lvgl/src/core/lv_obj_class.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file lv_obj_class.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_CLASS_H
|
||||
#define LV_OBJ_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
struct _lv_event_t;
|
||||
|
||||
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 void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e);
|
||||
/**
|
||||
* Describe the common methods of every object.
|
||||
* Similar to a C++ class.
|
||||
*/
|
||||
typedef struct _lv_obj_class_t {
|
||||
const struct _lv_obj_class_t * base_class;
|
||||
void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
|
||||
void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
void (*event_cb)(const struct _lv_obj_class_t * class_p,
|
||||
struct _lv_event_t * e); /**< Widget type specific event function*/
|
||||
lv_coord_t width_def;
|
||||
lv_coord_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;
|
||||
} lv_obj_class_t;
|
||||
|
||||
/**********************
|
||||
* 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
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent);
|
||||
|
||||
void lv_obj_class_init_obj(struct _lv_obj_t * obj);
|
||||
|
||||
void _lv_obj_destruct(struct _lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_editable(struct _lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_group_def(struct _lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_CLASS_H*/
|
||||
378
LVGL.Simulator/lvgl/src/core/lv_obj_draw.c
Normal file
378
LVGL.Simulator/lvgl/src/core/lv_obj_draw.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/**
|
||||
* @file lv_obj_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_draw.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev.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, uint32_t part, lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->radius = lv_obj_get_style_radius(obj, part);
|
||||
|
||||
lv_opa_t main_opa = part != LV_PART_MAIN ? lv_obj_get_style_opa(obj, part) : LV_OPA_COVER;
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN || main_opa <= LV_OPA_MIN) {
|
||||
draw_dsc->bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->border_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->outline_opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(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.dither = lv_obj_get_style_bg_dither_mode(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
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_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_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_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_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(main_opa < LV_OPA_MAX) {
|
||||
opa = (uint16_t)((uint16_t) main_opa * opa) >> 8;
|
||||
}
|
||||
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->bg_opa = (uint16_t)((uint16_t)draw_dsc->bg_opa * opa) >> 8;
|
||||
draw_dsc->bg_img_opa = (uint16_t)((uint16_t)draw_dsc->bg_img_opa * opa) >> 8;
|
||||
draw_dsc->border_opa = (uint16_t)((uint16_t)draw_dsc->border_opa * opa) >> 8;
|
||||
draw_dsc->shadow_opa = (uint16_t)((uint16_t)draw_dsc->shadow_opa * opa) >> 8;
|
||||
draw_dsc->outline_opa = (uint16_t)((uint16_t)draw_dsc->outline_opa * opa) >> 8;
|
||||
}
|
||||
#else /*LV_DRAW_COMPLEX*/
|
||||
if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
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_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_text_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part);
|
||||
draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part);
|
||||
draw_dsc->decor = lv_obj_get_style_text_decor(obj, part);
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
|
||||
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_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_img_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa_scale = lv_obj_get_style_opa(obj, part);
|
||||
if(opa_scale < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->angle = 0;
|
||||
draw_dsc->zoom = LV_IMG_ZOOM_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_img_recolor_opa(obj, part);
|
||||
if(draw_dsc->recolor_opa > 0) {
|
||||
draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->width = lv_obj_get_style_line_width(obj, part);
|
||||
if(draw_dsc->width == 0) return;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_line_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) 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 LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc)
|
||||
{
|
||||
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(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part);
|
||||
draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part);
|
||||
|
||||
draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_coord_t s = 0;
|
||||
|
||||
lv_coord_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);
|
||||
lv_coord_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
lv_coord_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
|
||||
sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y));
|
||||
s = LV_MAX(s, sh_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_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) {
|
||||
lv_coord_t outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
s = LV_MAX(s, outline_pad + outline_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, part);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, part);
|
||||
lv_coord_t wh = LV_MAX(w, h);
|
||||
if(wh > 0) s += wh;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_obj_draw_part_dsc_t));
|
||||
dsc->draw_ctx = draw_ctx;
|
||||
}
|
||||
|
||||
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type)
|
||||
{
|
||||
if(dsc->class_p == class_p && dsc->type == type) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_coord_t s_new = 0;
|
||||
lv_event_send(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new);
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
|
||||
/*Store the result if the special attrs already allocated*/
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
/*Allocate spec. attrs. only if the result is not zero.
|
||||
*Zero is the default value if the spec. attr. are not defined.*/
|
||||
else if(s_new != 0) {
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
lv_coord_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;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
163
LVGL.Simulator/lvgl/src/core/lv_obj_draw.h
Normal file
163
LVGL.Simulator/lvgl/src/core/lv_obj_draw.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @file lv_obj_draw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_DRAW_H
|
||||
#define LV_OBJ_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
|
||||
/** 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;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_ctx_t * draw_ctx; /**< Draw context*/
|
||||
const struct _lv_obj_class_t * class_p; /**< The class that sent the event */
|
||||
uint32_t type; /**< The type if part being draw. Element of `lv_<name>_draw_part_type_t` */
|
||||
lv_area_t * draw_area; /**< The area of the part being drawn*/
|
||||
lv_draw_rect_dsc_t *
|
||||
rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/
|
||||
lv_draw_label_dsc_t *
|
||||
label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/
|
||||
lv_draw_line_dsc_t *
|
||||
line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/
|
||||
lv_draw_img_dsc_t *
|
||||
img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/
|
||||
lv_draw_arc_dsc_t *
|
||||
arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/
|
||||
const lv_point_t *
|
||||
p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/
|
||||
const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/
|
||||
char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/
|
||||
uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/
|
||||
uint32_t part; /**< The current part for which the event is sent*/
|
||||
uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/
|
||||
lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/
|
||||
int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/
|
||||
const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */
|
||||
} lv_obj_draw_part_dsc_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(struct _lv_obj_t * obj, uint32_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(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Initialize an image draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_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(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Initialize an arc draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object, e.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Get the required extra size (around the object's part) to draw shadow, outline, value etc.
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object
|
||||
* @return the extra size required around the object
|
||||
*/
|
||||
lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part);
|
||||
|
||||
/**
|
||||
* Initialize a draw descriptor used in events.
|
||||
* @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EVENT_DRAW_PART_BEGIN/END` event.
|
||||
* @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`)
|
||||
*/
|
||||
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**
|
||||
* Check the type obj a part draw descriptor
|
||||
* @param dsc the descriptor (normally the event parameter)
|
||||
* @param class_p pointer to class to which `type` is related
|
||||
* @param type element of `lv_<name>_draw_part_type_t`
|
||||
* @return true if ::dsc is related to ::class_p and ::type
|
||||
*/
|
||||
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type);
|
||||
|
||||
/**
|
||||
* 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(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the extended draw area of an object.
|
||||
* @param obj pointer to an object
|
||||
* @return the size extended draw area around the real coordinates
|
||||
*/
|
||||
lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_DRAW_H*/
|
||||
1110
LVGL.Simulator/lvgl/src/core/lv_obj_pos.c
Normal file
1110
LVGL.Simulator/lvgl/src/core/lv_obj_pos.c
Normal file
File diff suppressed because it is too large
Load Diff
431
LVGL.Simulator/lvgl/src/core/lv_obj_pos.h
Normal file
431
LVGL.Simulator/lvgl/src/core/lv_obj_pos.h
Normal file
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
* @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
|
||||
**********************/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data);
|
||||
typedef struct {
|
||||
lv_layout_update_cb_t cb;
|
||||
void * user_data;
|
||||
} lv_layout_dsc_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(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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_SIZE_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(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_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(struct _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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _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 struct _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(struct _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 struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Register a new layout
|
||||
* @param cb the layout update callback
|
||||
* @param user_data custom data that will be passed to `cb`
|
||||
* @return the ID of the new layout
|
||||
*/
|
||||
uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data);
|
||||
|
||||
/**
|
||||
* 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(struct _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(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs);
|
||||
|
||||
/**
|
||||
* Align an object to an other object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param base pointer to an other 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(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs,
|
||||
lv_coord_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
|
||||
*/
|
||||
static inline void lv_obj_center(struct _lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x(const struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x2(const struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y(const struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the actually set x coordinate of object, i.e. the offset form the set alignment
|
||||
* @param obj pointer to an object
|
||||
* @return the set x coordinate
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the actually set y coordinate of object, i.e. the offset form the set alignment
|
||||
* @param obj pointer to an object
|
||||
* @return the set y coordinate
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y_aligned(const struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_width(const struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_height(const struct _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)
|
||||
*/
|
||||
lv_coord_t lv_obj_get_content_width(const struct _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)
|
||||
*/
|
||||
lv_coord_t lv_obj_get_content_height(const struct _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 struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_self_width(const struct _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.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_self_height(const struct _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(struct _lv_obj_t * obj);
|
||||
|
||||
void lv_obj_refr_pos(struct _lv_obj_t * obj);
|
||||
|
||||
void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
|
||||
void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating);
|
||||
|
||||
/**
|
||||
* 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 struct _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 struct _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 struct _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 struct _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(struct _lv_obj_t * obj, lv_coord_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 struct _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(struct _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
|
||||
*/
|
||||
lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_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
|
||||
*/
|
||||
lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_POS_H*/
|
||||
799
LVGL.Simulator/lvgl/src/core/lv_obj_scroll.c
Normal file
799
LVGL.Simulator/lvgl/src/core/lv_obj_scroll.c
Normal file
@@ -0,0 +1,799 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_scroll.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev_scroll.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 lv_res_t scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
static void scroll_x_anim(void * obj, int32_t v);
|
||||
static void scroll_y_anim(void * obj, int32_t v);
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a);
|
||||
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 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 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 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 obj->spec_attr->scroll_snap_y;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.y2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.y2 - pad_bottom - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_h = lv_obj_get_self_height(obj);
|
||||
self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom - 2 * border_width);
|
||||
self_h -= lv_obj_get_scroll_y(obj);
|
||||
return LV_MAX(child_res, self_h);
|
||||
}
|
||||
|
||||
lv_coord_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*/
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
lv_coord_t child_res = 0;
|
||||
|
||||
uint32_t i;
|
||||
lv_coord_t x1 = LV_COORD_MAX;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
x1 = LV_MIN(x1, child->coords.x1);
|
||||
|
||||
}
|
||||
|
||||
if(x1 != LV_COORD_MAX) {
|
||||
child_res = x1;
|
||||
child_res = (obj->coords.x1 + pad_left + border_width) - child_res;
|
||||
}
|
||||
else {
|
||||
child_res = LV_COORD_MIN;
|
||||
}
|
||||
|
||||
lv_coord_t self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w += lv_obj_get_scroll_x(obj);
|
||||
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
lv_coord_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*/
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.x2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.x2 - pad_right - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_w;
|
||||
self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w -= lv_obj_get_scroll_x(obj);
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
void lv_obj_get_scroll_end(struct _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, lv_coord_t dx, lv_coord_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 then naturally possible by the size of the content*/
|
||||
lv_coord_t x_current = -lv_obj_get_scroll_x(obj);
|
||||
lv_coord_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) {
|
||||
lv_coord_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) {
|
||||
lv_coord_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 then naturally possible by the size of the content*/
|
||||
lv_coord_t y_current = -lv_obj_get_scroll_y(obj);
|
||||
lv_coord_t y_bounded = y_current + dy;
|
||||
|
||||
if(y_bounded > 0) y_bounded = 0;
|
||||
if(y_bounded < 0) {
|
||||
lv_coord_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, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(dx == 0 && dy == 0) return;
|
||||
if(anim_en == LV_ANIM_ON) {
|
||||
lv_disp_t * d = lv_obj_get_disp(obj);
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_ready_cb(&a, scroll_anim_ready_cb);
|
||||
|
||||
if(dx) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 2) >> 2, 0, dx);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_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_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
if(dy) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 2) >> 2, 0, dy);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_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_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Remove pending animations*/
|
||||
lv_anim_del(obj, scroll_y_anim);
|
||||
lv_anim_del(obj, scroll_x_anim);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
res = scroll_by_raw(obj, dx, dy);
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_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, lv_coord_t x, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_x_anim);
|
||||
|
||||
lv_coord_t scroll_x = lv_obj_get_scroll_x(obj);
|
||||
lv_coord_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, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_y_anim);
|
||||
|
||||
lv_coord_t scroll_y = lv_obj_get_scroll_y(obj);
|
||||
lv_coord_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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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_dir_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;
|
||||
}
|
||||
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_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 ? true : false;
|
||||
|
||||
lv_coord_t top_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t bottom_space = lv_obj_get_style_pad_bottom(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t left_space = lv_obj_get_style_pad_left(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t right_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t tickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR);
|
||||
|
||||
lv_coord_t obj_h = lv_obj_get_height(obj);
|
||||
lv_coord_t obj_w = lv_obj_get_width(obj);
|
||||
|
||||
/*Space required for the vertical and horizontal scrollbars*/
|
||||
lv_coord_t ver_reg_space = ver_draw ? tickness : 0;
|
||||
lv_coord_t hor_req_space = hor_draw ? tickness : 0;
|
||||
lv_coord_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*/
|
||||
lv_coord_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 + tickness - 1;
|
||||
}
|
||||
else {
|
||||
ver_area->x2 = obj->coords.x2 - right_space;
|
||||
ver_area->x1 = ver_area->x2 - tickness + 1;
|
||||
}
|
||||
|
||||
lv_coord_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*/
|
||||
lv_coord_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 {
|
||||
lv_coord_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*/
|
||||
lv_coord_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 - tickness + 1;
|
||||
hor_area->x1 = obj->coords.x1;
|
||||
hor_area->x2 = obj->coords.x2;
|
||||
|
||||
lv_coord_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*/
|
||||
lv_coord_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 {
|
||||
lv_coord_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) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_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) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_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 lv_res_t scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(x == 0 && y == 0) return LV_RES_OK;
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
obj->spec_attr->scroll.x += x;
|
||||
obj->spec_attr->scroll.y += y;
|
||||
|
||||
lv_obj_move_children_by(obj, x, y, true);
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
lv_obj_invalidate(obj);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void scroll_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0);
|
||||
}
|
||||
|
||||
static void scroll_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj));
|
||||
}
|
||||
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_event_send(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);
|
||||
lv_coord_t snap_goal = 0;
|
||||
lv_coord_t act = 0;
|
||||
const lv_area_t * area_tmp;
|
||||
|
||||
lv_coord_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;
|
||||
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN);
|
||||
lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t top_diff = parent->coords.y1 + ptop - area_tmp->y1 - scroll_value->y;
|
||||
lv_coord_t bottom_diff = -(parent->coords.y2 - pbottom - area_tmp->y2 - scroll_value->y);
|
||||
lv_coord_t parent_h = lv_obj_get_height(parent) - ptop - pbottom;
|
||||
if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0;
|
||||
else if(top_diff > 0) {
|
||||
y_scroll = top_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_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*/
|
||||
lv_coord_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 + ptop;
|
||||
act = area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.y2 - pbottom;
|
||||
act = area_tmp->y2 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.y1 + ptop + parent_h / 2;
|
||||
act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_coord_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;
|
||||
|
||||
lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t left_diff = parent->coords.x1 + pleft - area_tmp->x1 - scroll_value->x;
|
||||
lv_coord_t right_diff = -(parent->coords.x2 - pright - 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*/
|
||||
lv_coord_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*/
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(parent);
|
||||
if(sr + x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
|
||||
lv_coord_t parent_w = lv_obj_get_width(parent) - pleft - pright;
|
||||
switch(snap_x) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.x1 + pleft;
|
||||
act = area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.x2 - pright;
|
||||
act = area_tmp->x2 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.x1 + pleft + parent_w / 2;
|
||||
act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Remove any pending scroll animations.*/
|
||||
bool y_del = lv_anim_del(parent, scroll_y_anim);
|
||||
bool x_del = lv_anim_del(parent, scroll_x_anim);
|
||||
if(y_del || x_del) {
|
||||
lv_res_t res;
|
||||
res = lv_event_send(parent, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
294
LVGL.Simulator/lvgl/src/core/lv_obj_scroll.h
Normal file
294
LVGL.Simulator/lvgl/src/core/lv_obj_scroll.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* @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"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
/** Scrollbar modes: shows when should the scrollbars be visible*/
|
||||
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*/
|
||||
};
|
||||
typedef uint8_t lv_scrollbar_mode_t;
|
||||
|
||||
|
||||
/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/
|
||||
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*/
|
||||
};
|
||||
typedef uint8_t 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(struct _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(struct _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(struct _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(struct _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 struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get 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`
|
||||
*/
|
||||
lv_dir_t lv_obj_get_scroll_dir(const struct _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 struct _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 struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_x(const struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_y(const struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_top(struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_bottom(struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_left(struct _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
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_right(struct _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(struct _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 dx pixels to scroll horizontally
|
||||
* @param dy pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
* @note > 0 value means scroll right/bottom (show the more content on the right/bottom)
|
||||
* @note e.g. dy = -20 means scroll down 20 px
|
||||
*/
|
||||
void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_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(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_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(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _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(struct _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 struct _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(struct _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(struct _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(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Checked 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(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_SCROLL_H*/
|
||||
824
LVGL.Simulator/lvgl/src/core/lv_obj_style.c
Normal file
824
LVGL.Simulator/lvgl/src/core/lv_obj_style.c
Normal file
@@ -0,0 +1,824 @@
|
||||
/**
|
||||
* @file lv_obj_style.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t * obj;
|
||||
lv_style_prop_t prop;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_value_t start_value;
|
||||
lv_style_value_t end_value;
|
||||
} trans_t;
|
||||
|
||||
typedef enum {
|
||||
CACHE_ZERO = 0,
|
||||
CACHE_TRUE = 1,
|
||||
CACHE_UNSET = 2,
|
||||
CACHE_255 = 3,
|
||||
CACHE_NEED_CHECK = 4,
|
||||
} cache_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector);
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part);
|
||||
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj);
|
||||
static void refresh_children_style(lv_obj_t * obj);
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit);
|
||||
static void trans_anim_cb(void * _tr, int32_t v);
|
||||
static void trans_anim_start_cb(lv_anim_t * a);
|
||||
static void trans_anim_ready_cb(lv_anim_t * a);
|
||||
static void fade_anim_cb(void * obj, int32_t v);
|
||||
static void fade_in_anim_ready(lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool style_refr = true;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_obj_style_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(trans_t));
|
||||
}
|
||||
|
||||
void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
trans_del(obj, selector, LV_STYLE_PROP_ANY, NULL);
|
||||
|
||||
uint32_t i;
|
||||
/*Go after the transition and local styles*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
if(obj->styles[i].is_local) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Now `i` is at the first normal style. Insert the new style before this*/
|
||||
|
||||
/*Allocate space for the new style and shift the rest of the style to the end*/
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
uint32_t j;
|
||||
for(j = obj->style_cnt - 1; j > i ; j--) {
|
||||
obj->styles[j] = obj->styles[j - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = style;
|
||||
obj->styles[i].selector = selector;
|
||||
|
||||
lv_obj_refresh_style(obj, selector, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
|
||||
void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
lv_state_t state = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
lv_style_prop_t prop = LV_STYLE_PROP_ANY;
|
||||
if(style && style->prop_cnt == 0) prop = LV_STYLE_PROP_INV;
|
||||
|
||||
uint32_t i = 0;
|
||||
bool deleted = false;
|
||||
while(i < obj->style_cnt) {
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if((state != LV_STATE_ANY && state_act != state) ||
|
||||
(part != LV_PART_ANY && part_act != part) ||
|
||||
(style != NULL && style != obj->styles[i].style)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_trans) {
|
||||
trans_del(obj, part, LV_STYLE_PROP_ANY, NULL);
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_local || obj->styles[i].is_trans) {
|
||||
lv_style_reset(obj->styles[i].style);
|
||||
lv_mem_free(obj->styles[i].style);
|
||||
obj->styles[i].style = NULL;
|
||||
}
|
||||
|
||||
/*Shift the styles after `i` by one*/
|
||||
uint32_t j;
|
||||
for(j = i; j < (uint32_t)obj->style_cnt - 1 ; j++) {
|
||||
obj->styles[j] = obj->styles[j + 1];
|
||||
}
|
||||
|
||||
obj->style_cnt--;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
deleted = true;
|
||||
/*The style from the current `i` index is removed, so `i` points to the next style.
|
||||
*Therefore it doesn't needs to be incremented*/
|
||||
}
|
||||
if(deleted && prop != LV_STYLE_PROP_INV) {
|
||||
lv_obj_refresh_style(obj, part, prop);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_report_style_change(lv_style_t * style)
|
||||
{
|
||||
if(!style_refr) return;
|
||||
lv_disp_t * d = lv_disp_get_next(NULL);
|
||||
|
||||
while(d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
report_style_change_core(style, d->screens[i]);
|
||||
}
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!style_refr) return;
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
|
||||
bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYOUT_REFR);
|
||||
bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_EXT_DRAW);
|
||||
bool is_inherit = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
|
||||
|
||||
if(is_layout_refr) {
|
||||
if(part == LV_PART_ANY ||
|
||||
part == LV_PART_MAIN ||
|
||||
lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT ||
|
||||
lv_obj_get_style_width(obj, 0) == LV_SIZE_CONTENT) {
|
||||
lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY || is_layout_refr)) {
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) lv_obj_mark_layout_as_dirty(parent);
|
||||
}
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY || is_ext_draw) {
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY || (is_inherit && (is_ext_draw || is_layout_refr))) {
|
||||
if(part != LV_PART_SCROLLBAR) {
|
||||
refresh_children_style(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_enable_style_refresh(bool en)
|
||||
{
|
||||
style_refr = en;
|
||||
}
|
||||
|
||||
lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop)
|
||||
{
|
||||
lv_style_value_t value_act;
|
||||
bool inherit = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
|
||||
bool found = false;
|
||||
while(obj) {
|
||||
found = get_prop_core(obj, part, prop, &value_act);
|
||||
if(found) break;
|
||||
if(!inherit) break;
|
||||
|
||||
/*If not found, check the `MAIN` style first*/
|
||||
if(part != LV_PART_MAIN) {
|
||||
part = LV_PART_MAIN;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check the parent too.*/
|
||||
obj = lv_obj_get_parent(obj);
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
|
||||
const lv_obj_class_t * cls = obj->class_p;
|
||||
while(cls) {
|
||||
if(prop == LV_STYLE_WIDTH) {
|
||||
if(cls->width_def != 0) break;
|
||||
}
|
||||
else {
|
||||
if(cls->height_def != 0) break;
|
||||
}
|
||||
cls = cls->base_class;
|
||||
}
|
||||
|
||||
if(cls) {
|
||||
value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def;
|
||||
}
|
||||
else {
|
||||
value_act.num = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value_act = lv_style_prop_get_default(prop);
|
||||
}
|
||||
}
|
||||
return value_act;
|
||||
}
|
||||
|
||||
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_t * style = get_local_style(obj, selector);
|
||||
lv_style_set_prop(style, prop, value);
|
||||
lv_obj_refresh_style(obj, selector, prop);
|
||||
}
|
||||
|
||||
|
||||
lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return lv_style_get_prop(obj->styles[i].style, prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
uint32_t i;
|
||||
/*Find the style*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The style is not found*/
|
||||
if(i == obj->style_cnt) return false;
|
||||
|
||||
return lv_style_remove_prop(obj->styles[i].style, prop);
|
||||
}
|
||||
|
||||
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_dsc)
|
||||
{
|
||||
trans_t * tr;
|
||||
|
||||
/*Get the previous and current values*/
|
||||
obj->skip_trans = 1;
|
||||
obj->state = prev_state;
|
||||
lv_style_value_t v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
lv_style_value_t v2 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->skip_trans = 0;
|
||||
|
||||
if(v1.ptr == v2.ptr && v1.num == v2.num && v1.color.full == v2.color.full) return;
|
||||
obj->state = prev_state;
|
||||
v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(obj, part);
|
||||
lv_style_set_prop(style_trans->style, tr_dsc->prop, v1); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
if(tr_dsc->prop == LV_STYLE_RADIUS) {
|
||||
if(v1.num == LV_RADIUS_CIRCLE || v2.num == LV_RADIUS_CIRCLE) {
|
||||
lv_coord_t whalf = lv_obj_get_width(obj) / 2;
|
||||
lv_coord_t hhalf = lv_obj_get_width(obj) / 2;
|
||||
if(v1.num == LV_RADIUS_CIRCLE) v1.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
if(v2.num == LV_RADIUS_CIRCLE) v2.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
}
|
||||
}
|
||||
|
||||
tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
LV_ASSERT_MALLOC(tr);
|
||||
if(tr == NULL) return;
|
||||
tr->start_value = v1;
|
||||
tr->end_value = v2;
|
||||
tr->obj = obj;
|
||||
tr->prop = tr_dsc->prop;
|
||||
tr->selector = part;
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, tr);
|
||||
lv_anim_set_exec_cb(&a, trans_anim_cb);
|
||||
lv_anim_set_start_cb(&a, trans_anim_start_cb);
|
||||
lv_anim_set_ready_cb(&a, trans_anim_ready_cb);
|
||||
lv_anim_set_values(&a, 0x00, 0xFF);
|
||||
lv_anim_set_time(&a, tr_dsc->time);
|
||||
lv_anim_set_delay(&a, tr_dsc->delay);
|
||||
lv_anim_set_path_cb(&a, tr_dsc->path_cb);
|
||||
lv_anim_set_early_apply(&a, false);
|
||||
#if LV_USE_USER_DATA
|
||||
a.user_data = tr_dsc->user_data;
|
||||
#endif
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
|
||||
lv_style_value_t _lv_obj_style_apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v)
|
||||
{
|
||||
if(obj == NULL) return v;
|
||||
const lv_color_filter_dsc_t * f = lv_obj_get_style_color_filter_dsc(obj, part);
|
||||
if(f && f->filter_cb) {
|
||||
lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part);
|
||||
if(f_opa != 0) v.color = f->filter_cb(f, v.color, f_opa);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
_lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2)
|
||||
{
|
||||
_lv_style_state_cmp_t res = _LV_STYLE_STATE_CMP_SAME;
|
||||
|
||||
/*Are there any new styles for the new state?*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
/*The style is valid for a state but not the other*/
|
||||
bool valid1 = state_act & (~state1) ? false : true;
|
||||
bool valid2 = state_act & (~state2) ? false : true;
|
||||
if(valid1 != valid2) {
|
||||
lv_style_t * style = obj->styles[i].style;
|
||||
lv_style_value_t v;
|
||||
/*If there is layout difference on the main part, return immediately. There is no more serious difference*/
|
||||
bool layout_diff = false;
|
||||
if(lv_style_get_prop(style, LV_STYLE_PAD_TOP, &v))layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_BOTTOM, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_LEFT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_RIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_COLUMN, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_ROW, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LAYOUT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_X, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_Y, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true;
|
||||
|
||||
if(layout_diff) {
|
||||
return _LV_STYLE_STATE_CMP_DIFF_LAYOUT;
|
||||
}
|
||||
|
||||
/*Check for draw pad changes*/
|
||||
if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_HEIGHT, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_PAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_SPREAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(res == _LV_STYLE_STATE_CMP_SAME) res = _LV_STYLE_STATE_CMP_DIFF_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, 0, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_ready_cb(&a, fade_in_anim_ready);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, lv_obj_get_style_opa(obj, 0), LV_OPA_TRANSP);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFFFF;
|
||||
}
|
||||
|
||||
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFF0000;
|
||||
}
|
||||
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt)
|
||||
{
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, part);
|
||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part);
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
return align;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the local style of an object for a given part and for a given state.
|
||||
* If the local style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param selector OR-ed value of parts and state for which the style should be get
|
||||
* @return pointer to the local style
|
||||
*/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
}
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
LV_ASSERT_MALLOC(obj->styles);
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
/*Copy only normal styles (not local and transition).
|
||||
*The new local style will be added as the last local style*/
|
||||
if(obj->styles[i - 1].is_local || obj->styles[i - 1].is_trans) break;
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[i].style);
|
||||
obj->styles[i].is_local = 1;
|
||||
obj->styles[i].selector = selector;
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transition style of an object for a given part and for a given state.
|
||||
* If the transition style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param selector OR-ed value of parts and state for which the style should be get
|
||||
* @return pointer to the transition style
|
||||
*/
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == selector) break;
|
||||
}
|
||||
|
||||
/*Already have a transition style for it*/
|
||||
if(i != obj->style_cnt) return &obj->styles[i];
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[0], sizeof(_lv_obj_style_t));
|
||||
obj->styles[0].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[0].style);
|
||||
obj->styles[0].is_trans = 1;
|
||||
obj->styles[0].selector = selector;
|
||||
return &obj->styles[0];
|
||||
}
|
||||
|
||||
|
||||
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
|
||||
{
|
||||
uint8_t group = 1 << _lv_style_get_prop_group(prop);
|
||||
int32_t weight = -1;
|
||||
lv_state_t state = obj->state;
|
||||
lv_state_t state_inv = ~state;
|
||||
lv_style_value_t value_tmp;
|
||||
bool skip_trans = obj->skip_trans;
|
||||
uint32_t i;
|
||||
bool found;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
if(obj_style->is_trans == false) break;
|
||||
if(skip_trans) continue;
|
||||
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
|
||||
if(part_act != part) continue;
|
||||
if((obj_style->style->has_group & group) == 0) continue;
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
if(found) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < obj->style_cnt; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
if(part_act != part) continue;
|
||||
|
||||
if((obj_style->style->has_group & group) == 0) continue;
|
||||
|
||||
/*Be sure the style not specifies other state than the requested.
|
||||
*E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/
|
||||
if((state_act & state_inv)) continue;
|
||||
|
||||
/*Check only better candidates*/
|
||||
if(state_act <= weight) continue;
|
||||
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
|
||||
if(found) {
|
||||
if(state_act == state) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
if(weight < state_act) {
|
||||
weight = state_act;
|
||||
*v = value_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(weight >= 0) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the style of all children of an object. (Called recursively)
|
||||
* @param style refresh objects only with this
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(style == NULL || obj->styles[i].style == style) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
report_style_change_core(style, obj->spec_attr->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively refresh the style of the children. Go deeper until a not NULL style is found
|
||||
* because the NULL styles are inherited from the parent
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void refresh_children_style(lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_invalidate(child);
|
||||
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_invalidate(child);
|
||||
|
||||
refresh_children_style(child); /*Check children too*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the transition from object's part's property.
|
||||
* - Remove the transition from `_lv_obj_style_trans_ll` and free it
|
||||
* - Delete pending transitions
|
||||
* @param obj pointer to an object which transition(s) should be removed
|
||||
* @param part a part of object or 0xFF to remove from all parts
|
||||
* @param prop a property or 0xFF to remove all properties
|
||||
* @param tr_limit delete transitions only "older" than this. `NULL` if not used
|
||||
*/
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit)
|
||||
{
|
||||
trans_t * tr;
|
||||
trans_t * tr_prev;
|
||||
bool removed = false;
|
||||
tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
while(tr != NULL) {
|
||||
if(tr == tr_limit) break;
|
||||
|
||||
/*'tr' might be deleted, so get the next object while 'tr' is valid*/
|
||||
tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
|
||||
if(tr->obj == obj && (part == tr->selector || part == LV_PART_ANY) && (prop == tr->prop || prop == LV_STYLE_PROP_ANY)) {
|
||||
/*Remove any transitioned properties from the trans. style
|
||||
*to allow changing it by normal styles*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && (part == LV_PART_ANY || obj->styles[i].selector == part)) {
|
||||
lv_style_remove_prop(obj->styles[i].style, tr->prop);
|
||||
}
|
||||
}
|
||||
|
||||
/*Free the transition descriptor too*/
|
||||
lv_anim_del(tr, NULL);
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
removed = true;
|
||||
|
||||
}
|
||||
tr = tr_prev;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
static void trans_anim_cb(void * _tr, int32_t v)
|
||||
{
|
||||
trans_t * tr = _tr;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans == 0 || obj->styles[i].selector != tr->selector) continue;
|
||||
|
||||
lv_style_value_t value_final;
|
||||
switch(tr->prop) {
|
||||
|
||||
case LV_STYLE_BORDER_SIDE:
|
||||
case LV_STYLE_BORDER_POST:
|
||||
case LV_STYLE_BLEND_MODE:
|
||||
if(v < 255) value_final.num = tr->start_value.num;
|
||||
else value_final.num = tr->end_value.num;
|
||||
break;
|
||||
case LV_STYLE_TRANSITION:
|
||||
case LV_STYLE_TEXT_FONT:
|
||||
if(v < 255) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_COLOR_FILTER_DSC:
|
||||
if(tr->start_value.ptr == NULL) value_final.ptr = tr->end_value.ptr;
|
||||
else if(tr->end_value.ptr == NULL) value_final.ptr = tr->start_value.ptr;
|
||||
else if(v < 128) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_BG_COLOR:
|
||||
case LV_STYLE_BORDER_COLOR:
|
||||
case LV_STYLE_TEXT_COLOR:
|
||||
case LV_STYLE_SHADOW_COLOR:
|
||||
case LV_STYLE_OUTLINE_COLOR:
|
||||
case LV_STYLE_IMG_RECOLOR:
|
||||
if(v <= 0) value_final.color = tr->start_value.color;
|
||||
else if(v >= 255) value_final.color = tr->end_value.color;
|
||||
else value_final.color = lv_color_mix(tr->end_value.color, tr->start_value.color, v);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(v == 0) value_final.num = tr->start_value.num;
|
||||
else if(v == 255) value_final.num = tr->end_value.num;
|
||||
else value_final.num = tr->start_value.num + ((int32_t)((int32_t)(tr->end_value.num - tr->start_value.num) * v) >> 8);
|
||||
break;
|
||||
}
|
||||
|
||||
lv_style_value_t old_value;
|
||||
bool refr = true;
|
||||
if(lv_style_get_prop(obj->styles[i].style, tr->prop, &old_value)) {
|
||||
if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full &&
|
||||
value_final.num == old_value.num) {
|
||||
refr = false;
|
||||
}
|
||||
}
|
||||
lv_style_set_prop(obj->styles[i].style, tr->prop, value_final);
|
||||
if(refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_start_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(tr->selector);
|
||||
tr->start_value = lv_obj_get_style_prop(tr->obj, part, tr->prop);
|
||||
|
||||
/*Init prop to an invalid values to be sure `trans_del` won't delete this added `tr`*/
|
||||
lv_style_prop_t prop_tmp = tr->prop;
|
||||
tr->prop = LV_STYLE_PROP_INV;
|
||||
|
||||
/*Delete the related transitions if any*/
|
||||
trans_del(tr->obj, part, prop_tmp, tr);
|
||||
|
||||
tr->prop = prop_tmp;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(tr->obj, tr->selector);
|
||||
lv_style_set_prop(style_trans->style, tr->prop, tr->start_value); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
lv_style_prop_t prop = tr->prop;
|
||||
|
||||
/*Remove the transitioned property from trans. style
|
||||
*if there no more transitions for this property
|
||||
*It allows changing it by normal styles*/
|
||||
bool running = false;
|
||||
trans_t * tr_i;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) {
|
||||
if(tr_i != tr && tr_i->obj == tr->obj && tr_i->selector == tr->selector && tr_i->prop == tr->prop) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!running) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == tr->selector) {
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_style_remove_prop(obj_style->style, prop);
|
||||
|
||||
if(lv_style_is_empty(obj->styles[i].style)) {
|
||||
lv_obj_remove_style(obj, obj_style->style, obj_style->selector);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fade_anim_cb(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void fade_in_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
}
|
||||
|
||||
|
||||
245
LVGL.Simulator/lvgl/src/core/lv_obj_style.h
Normal file
245
LVGL.Simulator/lvgl/src/core/lv_obj_style.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* @file lv_obj_style.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_STYLE_H
|
||||
#define LV_OBJ_STYLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
_LV_STYLE_STATE_CMP_SAME, /*The style properties in the 2 states are identical*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_REDRAW, /*The differences can be shown with a simple redraw*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_DRAW_PAD, /*The differences can be shown with a simple redraw*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_LAYOUT, /*The differences can be shown with a simple redraw*/
|
||||
} _lv_style_state_cmp_t;
|
||||
|
||||
typedef uint32_t lv_style_selector_t;
|
||||
|
||||
typedef struct {
|
||||
lv_style_t * style;
|
||||
uint32_t selector : 24;
|
||||
uint32_t is_local : 1;
|
||||
uint32_t is_trans : 1;
|
||||
} _lv_obj_style_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t time;
|
||||
uint16_t delay;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_prop_t prop;
|
||||
lv_anim_path_cb_t path_cb;
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
} _lv_obj_style_transition_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the object related style manager module.
|
||||
* Called by LVGL in `lv_init()`
|
||||
*/
|
||||
void _lv_obj_style_init(void);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @example lv_obj_add_style(btn, &style_btn, 0); //Default button style
|
||||
* @example lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed
|
||||
*/
|
||||
void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Add a style to 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
|
||||
* @example lv_obj_remove_style(obj, &style, LV_PART_ANY | LV_STATE_ANY); //Remove a specific style
|
||||
* @example lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part
|
||||
* @example lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles
|
||||
*/
|
||||
void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Remove all styles from an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(struct _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 struct _lv_obj_t * obj, lv_part_t part, 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(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* 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(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Used internally for color filtering
|
||||
*/
|
||||
lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, uint32_t part, lv_style_value_t v);
|
||||
|
||||
/**
|
||||
* Used internally to create a style transition
|
||||
* @param obj
|
||||
* @param part
|
||||
* @param prev_state
|
||||
* @param new_state
|
||||
* @param tr
|
||||
*/
|
||||
void _lv_obj_style_create_transition(struct _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(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2);
|
||||
|
||||
/**
|
||||
* 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(struct _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(struct _lv_obj_t * obj, uint32_t time, uint32_t delay);
|
||||
|
||||
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector);
|
||||
|
||||
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector);
|
||||
|
||||
#include "lv_obj_style_gen.h"
|
||||
|
||||
static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_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_pad_gap(struct _lv_obj_t * obj, lv_coord_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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_width(obj, value, selector);
|
||||
lv_obj_set_style_height(obj, value, selector);
|
||||
}
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_STYLE_H*/
|
||||
657
LVGL.Simulator/lvgl/src/core/lv_obj_style_gen.c
Normal file
657
LVGL.Simulator/lvgl/src/core/lv_obj_style_gen.c
Normal file
@@ -0,0 +1,657 @@
|
||||
#include "lv_obj.h"
|
||||
|
||||
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_align(struct _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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ZOOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ANGLE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_TOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_BOTTOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_LEFT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_RIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_ROW, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.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(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad(struct _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_dither_mode(struct _lv_obj_t * obj, lv_dither_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_BG_DITHER_MODE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_src(struct _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_IMG_SRC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_opa(struct _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_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_tiled(struct _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_IMG_TILED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_side(struct _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(struct _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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_PAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_SPREAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_opa(struct _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_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_rounded(struct _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(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_rounded(struct _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(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_img_src(struct _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_IMG_SRC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_font(struct _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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LETTER_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LINE_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_decor(struct _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(struct _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(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_RADIUS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_clip_corner(struct _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(struct _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_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_DSC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_color_filter_opa(struct _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(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_TIME, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_speed(struct _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_SPEED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
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(struct _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(struct _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(struct _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);
|
||||
}
|
||||
634
LVGL.Simulator/lvgl/src/core/lv_obj_style_gen.h
Normal file
634
LVGL.Simulator/lvgl/src/core/lv_obj_style_gen.h
Normal file
@@ -0,0 +1,634 @@
|
||||
static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ZOOM);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ANGLE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD);
|
||||
return (const lv_grad_dsc_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_dither_mode_t lv_obj_get_style_bg_dither_mode(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_DITHER_MODE);
|
||||
return (lv_dither_mode_t)v.num;
|
||||
}
|
||||
|
||||
static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_SRC);
|
||||
return (const void *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR));
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_TILED);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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_img_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR));
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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_img_src(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMG_SRC);
|
||||
return (const void *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = _lv_obj_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC);
|
||||
return (const lv_color_filter_dsc_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM);
|
||||
return (const lv_anim_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME);
|
||||
return (uint32_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED);
|
||||
return (uint32_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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 struct _lv_obj_t * obj, uint32_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;
|
||||
}
|
||||
|
||||
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector);
|
||||
452
LVGL.Simulator/lvgl/src/core/lv_obj_tree.c
Normal file
452
LVGL.Simulator/lvgl/src/core/lv_obj_tree.c
Normal file
@@ -0,0 +1,452 @@
|
||||
/**
|
||||
* @file lv_obj_tree.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_async.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_del_async_cb(void * obj);
|
||||
static void obj_del_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 VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_del(lv_obj_t * obj)
|
||||
{
|
||||
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);
|
||||
if(par) {
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
}
|
||||
|
||||
lv_disp_t * disp = NULL;
|
||||
bool act_scr_del = false;
|
||||
if(par == NULL) {
|
||||
disp = lv_obj_get_disp(obj);
|
||||
if(!disp) return; /*Shouldn't happen*/
|
||||
if(disp->act_scr == obj) act_scr_del = true;
|
||||
}
|
||||
|
||||
obj_del_core(obj);
|
||||
|
||||
/*Call the ancestor's event handler to the parent to notify it about the child delete*/
|
||||
if(par) {
|
||||
lv_obj_update_layout(par);
|
||||
lv_obj_readjust_scroll(par, LV_ANIM_OFF);
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_event_send(par, LV_EVENT_CHILD_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*Handle if the active screen was deleted*/
|
||||
if(act_scr_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 (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
/*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;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_del_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_time(&a, 1);
|
||||
lv_anim_set_delay(&a, delay_ms);
|
||||
lv_anim_set_ready_cb(&a, lv_obj_del_anim_ready_cb);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_del_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_del(a->var);
|
||||
}
|
||||
|
||||
void lv_obj_del_async(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_async_call(lv_obj_del_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;
|
||||
}
|
||||
|
||||
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_cnt(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_mem_realloc(old_parent->spec_attr->children,
|
||||
old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
}
|
||||
else {
|
||||
lv_mem_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_mem_realloc(parent->spec_attr->children,
|
||||
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj;
|
||||
|
||||
obj->parent = parent;
|
||||
|
||||
/*Notify the original parent because one of its children is lost*/
|
||||
lv_obj_readjust_scroll(old_parent, LV_ANIM_OFF);
|
||||
lv_obj_scrollbar_invalidate(old_parent);
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_DELETED, NULL);
|
||||
|
||||
/*Notify the new parent about the child*/
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(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);
|
||||
|
||||
if(index < 0) {
|
||||
index = lv_obj_get_child_cnt(lv_obj_get_parent(obj)) + index;
|
||||
}
|
||||
|
||||
const int32_t old_index = lv_obj_get_index(obj);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
|
||||
if(index < 0) return;
|
||||
if(index >= (int32_t) lv_obj_get_child_cnt(parent)) return;
|
||||
if(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_event_send(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_event_send(parent2, LV_EVENT_CHILD_DELETED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_DELETED, obj1);
|
||||
|
||||
parent->spec_attr->children[index1] = obj2;
|
||||
parent2->spec_attr->children[index2] = obj1;
|
||||
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj2);
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_CHANGED, obj1);
|
||||
lv_event_send(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_disp_t * lv_obj_get_disp(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_disp_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), 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 id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
uint32_t idu;
|
||||
if(id < 0) {
|
||||
id = obj->spec_attr->child_cnt + id;
|
||||
if(id < 0) return NULL;
|
||||
idu = (uint32_t) id;
|
||||
}
|
||||
else {
|
||||
idu = id;
|
||||
}
|
||||
|
||||
if(idu >= obj->spec_attr->child_cnt) return NULL;
|
||||
else return obj->spec_attr->children[id];
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_child_cnt(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_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 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(parent); i++) {
|
||||
if(lv_obj_get_child(parent, i) == obj) return i;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF; /*Shouldn't happen*/
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_del_async_cb(void * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_del(obj);
|
||||
}
|
||||
|
||||
static void obj_del_core(lv_obj_t * obj)
|
||||
{
|
||||
/*Let the user free the resources used in `LV_EVENT_DELETE`*/
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL);
|
||||
if(res == LV_RES_INV) return;
|
||||
|
||||
/*Recursively delete the children*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_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) {
|
||||
if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
if(indev->proc.types.pointer.last_pressed == obj) {
|
||||
indev->proc.types.pointer.last_pressed = NULL;
|
||||
}
|
||||
|
||||
if(indev->group == group && obj == lv_indev_get_obj_act()) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
/*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_disp_t * disp = lv_obj_get_disp(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_mem_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
/*Remove the object from the child list of its parent*/
|
||||
else {
|
||||
uint32_t id = lv_obj_get_index(obj);
|
||||
uint32_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_mem_realloc(obj->parent->spec_attr->children,
|
||||
obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
|
||||
/*Free the object itself*/
|
||||
lv_mem_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_disp_t * disp = lv_disp_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_disp_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_cnt(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;
|
||||
}
|
||||
172
LVGL.Simulator/lvgl/src/core/lv_obj_tree.h
Normal file
172
LVGL.Simulator/lvgl/src/core/lv_obj_tree.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @file struct _lv_obj_tree.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_TREE_H
|
||||
#define LV_OBJ_TREE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
|
||||
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)(struct _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_del(struct _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(struct _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_del_delayed(struct _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_del_anim_ready_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_del_async(struct _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(struct _lv_obj_t * obj, struct _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(struct _lv_obj_t * obj1, struct _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(struct _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
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the display of the object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the object's display
|
||||
*/
|
||||
lv_disp_t * lv_obj_get_disp(const struct _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)
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_parent(const struct _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 id 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
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id);
|
||||
|
||||
/**
|
||||
* Get the number of children
|
||||
* @param obj pointer to an object
|
||||
* @return the number of children
|
||||
*/
|
||||
uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
uint32_t lv_obj_get_index(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* 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(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_TREE_H*/
|
||||
1088
LVGL.Simulator/lvgl/src/core/lv_refr.c
Normal file
1088
LVGL.Simulator/lvgl/src/core/lv_refr.c
Normal file
File diff suppressed because it is too large
Load Diff
115
LVGL.Simulator/lvgl/src/core/lv_refr.h
Normal file
115
LVGL.Simulator/lvgl/src/core/lv_refr.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file lv_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_REFR_H
|
||||
#define LV_REFR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void _lv_refr_init(void);
|
||||
|
||||
/**
|
||||
* 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_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Redrawn on object an all its children using the passed draw context
|
||||
* @param draw pointer to an initialized draw context
|
||||
* @param obj the start object from the redraw should start
|
||||
*/
|
||||
void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* 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_disp_t * disp, const lv_area_t * area_p);
|
||||
|
||||
/**
|
||||
* Get the display which is being refreshed
|
||||
* @return the display being refreshed
|
||||
*/
|
||||
lv_disp_t * _lv_refr_get_disp_refreshing(void);
|
||||
|
||||
/**
|
||||
* Set the display which is being refreshed.
|
||||
* It shouldn't be used directly by the user.
|
||||
* It can be used to trick the drawing functions about there is an active display.
|
||||
* @param the display being refreshed
|
||||
*/
|
||||
void _lv_refr_set_disp_refreshing(lv_disp_t * disp);
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
/**
|
||||
* Reset FPS counter
|
||||
*/
|
||||
void lv_refr_reset_fps_counter(void);
|
||||
|
||||
/**
|
||||
* Get the average FPS
|
||||
* @return the average FPS
|
||||
*/
|
||||
uint32_t lv_refr_get_fps_avg(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called periodically to handle the refreshing
|
||||
* @param timer pointer to the timer itself
|
||||
*/
|
||||
void _lv_disp_refr_timer(lv_timer_t * timer);
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_REFR_H*/
|
||||
118
LVGL.Simulator/lvgl/src/core/lv_theme.c
Normal file
118
LVGL.Simulator/lvgl/src/core/lv_theme.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file lv_theme.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = obj ? lv_obj_get_disp(obj) : lv_disp_get_default();
|
||||
return lv_disp_get_theme(disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active theme on an object
|
||||
* @param obj pointer to an object
|
||||
* @param name the name of the theme element to apply. E.g. `LV_THEME_BTN`
|
||||
*/
|
||||
void lv_theme_apply(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
if(th == NULL) return;
|
||||
|
||||
lv_obj_remove_style_all(obj);
|
||||
|
||||
apply_theme(th, obj); /*Apply the theme including the base theme(s)*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a base theme for a theme.
|
||||
* The styles from the base them will be added before the styles of the current theme.
|
||||
* Arbitrary long chain of themes can be created by setting base themes.
|
||||
* @param new_theme pointer to theme which base should be set
|
||||
* @param base pointer to the base theme
|
||||
*/
|
||||
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * base)
|
||||
{
|
||||
new_theme->parent = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback for a theme.
|
||||
* The callback is used to add styles to different objects
|
||||
* @param theme pointer to theme which callback should be set
|
||||
* @param cb pointer to the callback
|
||||
*/
|
||||
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb)
|
||||
{
|
||||
theme->apply_cb = apply_cb;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_small : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_normal : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_large : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_primary : lv_palette_main(LV_PALETTE_BLUE_GREY);
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_secondary : lv_palette_main(LV_PALETTE_BLUE);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj)
|
||||
{
|
||||
if(th->parent) apply_theme(th->parent, obj);
|
||||
if(th->apply_cb) th->apply_cb(th, obj);
|
||||
}
|
||||
120
LVGL.Simulator/lvgl/src/core/lv_theme.h
Normal file
120
LVGL.Simulator/lvgl/src/core/lv_theme.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
*@file lv_theme.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_THEME_H
|
||||
#define LV_THEME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_theme_t;
|
||||
struct _lv_disp_t;
|
||||
|
||||
typedef void (*lv_theme_apply_cb_t)(struct _lv_theme_t *, lv_obj_t *);
|
||||
|
||||
typedef struct _lv_theme_t {
|
||||
lv_theme_apply_cb_t apply_cb;
|
||||
struct _lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/
|
||||
void * user_data;
|
||||
struct _lv_disp_t * disp;
|
||||
lv_color_t color_primary;
|
||||
lv_color_t color_secondary;
|
||||
const lv_font_t * font_small;
|
||||
const lv_font_t * font_normal;
|
||||
const lv_font_t * font_large;
|
||||
uint32_t flags; /*Any custom flag used by the theme*/
|
||||
} lv_theme_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the theme assigned to the display of the object
|
||||
* @param obj pointer to a theme object
|
||||
* @return the theme of the object's display (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Apply the active theme on an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_theme_apply(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set a base theme for a theme.
|
||||
* The styles from the base them will be added before the styles of the current theme.
|
||||
* Arbitrary long chain of themes can be created by setting base themes.
|
||||
* @param new_theme pointer to theme which base should be set
|
||||
* @param parent pointer to the base theme
|
||||
*/
|
||||
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent);
|
||||
|
||||
/**
|
||||
* Set an apply callback for a theme.
|
||||
* The apply callback is used to add styles to different objects
|
||||
* @param theme pointer to theme which callback should be set
|
||||
* @param apply_cb pointer to the callback
|
||||
*/
|
||||
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb);
|
||||
|
||||
/**
|
||||
* Get the small font of the theme
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj);
|
||||
/**
|
||||
* Get the normal font of the theme
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the subtitle font of the theme
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the primary color of the theme
|
||||
* @param obj pointer to an object
|
||||
* @return the color
|
||||
*/
|
||||
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the secondary color of the theme
|
||||
* @param obj pointer to an object
|
||||
* @return the color
|
||||
*/
|
||||
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_THEME_H*/
|
||||
6
LVGL.Simulator/lvgl/src/draw/arm2d/lv_draw_arm2d.mk
Normal file
6
LVGL.Simulator/lvgl/src/draw/arm2d/lv_draw_arm2d.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
CSRCS += lv_gpu_arm2d.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d"
|
||||
1065
LVGL.Simulator/lvgl/src/draw/arm2d/lv_gpu_arm2d.c
Normal file
1065
LVGL.Simulator/lvgl/src/draw/arm2d/lv_gpu_arm2d.c
Normal file
File diff suppressed because it is too large
Load Diff
51
LVGL.Simulator/lvgl/src/draw/arm2d/lv_gpu_arm2d.h
Normal file
51
LVGL.Simulator/lvgl/src/draw/arm2d/lv_gpu_arm2d.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file lv_gpu_arm2d.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GPU_ARM2D_H
|
||||
#define LV_GPU_ARM2D_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../hal/lv_hal_disp.h"
|
||||
#include "../sw/lv_draw_sw.h"
|
||||
|
||||
#if LV_USE_GPU_ARM2D
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef lv_draw_sw_ctx_t lv_draw_arm2d_ctx_t;
|
||||
|
||||
struct _lv_disp_drv_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_arm2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_arm2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_ARM2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_ARM2D_H*/
|
||||
48
LVGL.Simulator/lvgl/src/draw/lv_draw.c
Normal file
48
LVGL.Simulator/lvgl/src/draw/lv_draw.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file lv_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_init(void)
|
||||
{
|
||||
/*Nothing to init now*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
138
LVGL.Simulator/lvgl/src/draw/lv_draw.h
Normal file
138
LVGL.Simulator/lvgl/src/draw/lv_draw.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file lv_draw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_H
|
||||
#define LV_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_txt.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_img_cache.h"
|
||||
|
||||
#include "lv_draw_rect.h"
|
||||
#include "lv_draw_label.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_draw_line.h"
|
||||
#include "lv_draw_triangle.h"
|
||||
#include "lv_draw_arc.h"
|
||||
#include "lv_draw_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
void * user_data;
|
||||
} lv_draw_mask_t;
|
||||
|
||||
|
||||
typedef struct _lv_draw_ctx_t {
|
||||
/**
|
||||
* Pointer to a buffer to draw into
|
||||
*/
|
||||
void * buf;
|
||||
|
||||
/**
|
||||
* The position and size of `buf` (absolute coordinates)
|
||||
*/
|
||||
lv_area_t * buf_area;
|
||||
|
||||
/**
|
||||
* The current clip area with absolute coordinates, always the same or smaller than `buf_area`
|
||||
*/
|
||||
const lv_area_t * clip_area;
|
||||
|
||||
|
||||
void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
||||
|
||||
void (*draw_img_decoded)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
|
||||
|
||||
lv_res_t (*draw_img)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
void (*draw_letter)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
|
||||
void (*draw_line)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2);
|
||||
|
||||
|
||||
void (*draw_polygon)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc,
|
||||
const lv_point_t * points, uint16_t point_cnt);
|
||||
|
||||
/**
|
||||
* Replace the buffer with a rect without decoration like radius or borders
|
||||
*/
|
||||
void (*draw_bg)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_area_t * coords);
|
||||
|
||||
/**
|
||||
* Wait until all background operations are finished. (E.g. GPU operations)
|
||||
*/
|
||||
void (*wait_for_finish)(struct _lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**
|
||||
* Copy an area from buffer to an other
|
||||
* @param draw_ctx pointer to a draw context
|
||||
* @param dest_buf copy the buffer into this buffer
|
||||
* @param dest_stride the width of the dest_buf in pixels
|
||||
* @param dest_area the destination area
|
||||
* @param src_buf copy from this buffer
|
||||
* @param src_stride the width of src_buf in pixels
|
||||
* @param src_area the source area.
|
||||
*
|
||||
* @note dest_area and src_area must have the same width and height
|
||||
* but can have different x and y position.
|
||||
* @note dest_area and src_area must be clipped to the real dimensions of the buffers
|
||||
*/
|
||||
void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride,
|
||||
const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
|
||||
} lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_init(void);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* POST INCLUDES
|
||||
*********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_H*/
|
||||
23
LVGL.Simulator/lvgl/src/draw/lv_draw.mk
Normal file
23
LVGL.Simulator/lvgl/src/draw/lv_draw.mk
Normal file
@@ -0,0 +1,23 @@
|
||||
CSRCS += lv_draw_arc.c
|
||||
CSRCS += lv_draw.c
|
||||
CSRCS += lv_draw_img.c
|
||||
CSRCS += lv_draw_label.c
|
||||
CSRCS += lv_draw_line.c
|
||||
CSRCS += lv_draw_mask.c
|
||||
CSRCS += lv_draw_rect.c
|
||||
CSRCS += lv_draw_triangle.c
|
||||
CSRCS += lv_img_buf.c
|
||||
CSRCS += lv_img_cache.c
|
||||
CSRCS += lv_img_decoder.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw"
|
||||
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d/lv_draw_arm2d.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_pxp/lv_draw_nxp_pxp.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_vglite/lv_draw_nxp_vglite.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl/lv_draw_sdl.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk
|
||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk
|
||||
152
LVGL.Simulator/lvgl/src/draw/lv_draw_arc.c
Normal file
152
LVGL.Simulator/lvgl/src/draw/lv_draw_arc.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file lv_draw_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_arc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_arc_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
void lv_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius,
|
||||
uint16_t start_angle, uint16_t end_angle)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->width == 0) return;
|
||||
if(start_angle == end_angle) return;
|
||||
|
||||
draw_ctx->draw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
||||
|
||||
// const lv_draw_backend_t * backend = lv_draw_backend_get();
|
||||
// backend->draw_arc(center_x, center_y, radius, start_angle, end_angle, clip_area, dsc);
|
||||
}
|
||||
|
||||
void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
lv_coord_t w, bool rounded, lv_area_t * area)
|
||||
{
|
||||
lv_coord_t rout = radius;
|
||||
|
||||
/*Special case: full arc invalidation */
|
||||
if(end_angle == start_angle + 360) {
|
||||
area->x1 = x - rout;
|
||||
area->y1 = y - rout;
|
||||
area->x2 = x + rout;
|
||||
area->y2 = y + rout;
|
||||
return;
|
||||
}
|
||||
|
||||
if(start_angle > 360) start_angle -= 360;
|
||||
if(end_angle > 360) end_angle -= 360;
|
||||
|
||||
lv_coord_t rin = radius - w;
|
||||
lv_coord_t extra_area = rounded ? w / 2 + 1 : 0;
|
||||
uint8_t start_quarter = start_angle / 90;
|
||||
uint8_t end_quarter = end_angle / 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 <= end_angle) {
|
||||
if(start_quarter == 0) {
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 1) {
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 2) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
}
|
||||
else if(start_quarter == 0 && end_quarter == 1) {
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle),
|
||||
lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 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) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90),
|
||||
lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 2 && end_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y - rout - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin,
|
||||
lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3 && end_quarter == 0) {
|
||||
area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90),
|
||||
lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + rout + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * 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
|
||||
**********************/
|
||||
83
LVGL.Simulator/lvgl/src/draw/lv_draw_arc.h
Normal file
83
LVGL.Simulator/lvgl/src/draw/lv_draw_arc.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @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_color_t color;
|
||||
lv_coord_t width;
|
||||
uint16_t start_angle;
|
||||
uint16_t end_angle;
|
||||
const void * img_src;
|
||||
lv_opa_t opa;
|
||||
lv_blend_mode_t blend_mode : 2;
|
||||
uint8_t rounded : 1;
|
||||
} lv_draw_arc_dsc_t;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Draw an arc. (Can draw pie too with great thickness.)
|
||||
* @param center_x the x coordinate of the center of the arc
|
||||
* @param center_y the y coordinate of the center of the arc
|
||||
* @param radius the radius of the arc
|
||||
* @param mask the arc will be drawn only in this mask
|
||||
* @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 clip_area the arc will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
||||
|
||||
/**
|
||||
* 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(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
lv_coord_t w, bool rounded, lv_area_t * area);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_ARC_H*/
|
||||
355
LVGL.Simulator/lvgl/src/draw/lv_draw_img.c
Normal file
355
LVGL.Simulator/lvgl/src/draw/lv_draw_img.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* @file lv_draw_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg);
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_img_dsc_t));
|
||||
dsc->recolor = lv_color_black();
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->zoom = LV_IMG_ZOOM_NONE;
|
||||
dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw an image
|
||||
* @param coords the coordinates of the image
|
||||
* @param mask the image will be drawn only in this area
|
||||
* @param src pointer to a lv_color_t array which contains the pixels of the image
|
||||
* @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const void * src)
|
||||
{
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
show_error(draw_ctx, coords, "No\ndata");
|
||||
return;
|
||||
}
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_res_t res;
|
||||
if(draw_ctx->draw_img) {
|
||||
res = draw_ctx->draw_img(draw_ctx, dsc, coords, src);
|
||||
}
|
||||
else {
|
||||
res = decode_and_draw(draw_ctx, dsc, coords, src);
|
||||
}
|
||||
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
show_error(draw_ctx, coords, "No\ndata");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf)
|
||||
{
|
||||
uint8_t px_size = 0;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_UNKNOWN:
|
||||
case LV_IMG_CF_RAW:
|
||||
px_size = 0;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
px_size = LV_COLOR_SIZE;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE << 3;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
px_size = 1;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
px_size = 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
px_size = 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
px_size = 8;
|
||||
break;
|
||||
default:
|
||||
px_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return px_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color format is chroma keyed or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf)
|
||||
{
|
||||
bool is_chroma_keyed = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
case LV_IMG_CF_RAW_CHROMA_KEYED:
|
||||
is_chroma_keyed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
is_chroma_keyed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return is_chroma_keyed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color format has alpha channel or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf)
|
||||
{
|
||||
bool has_alpha = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
case LV_IMG_CF_RAW_ALPHA:
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
has_alpha = true;
|
||||
break;
|
||||
default:
|
||||
has_alpha = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return has_alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
* @param src pointer to an image source:
|
||||
* - pointer to an 'lv_img_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_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
|
||||
*/
|
||||
lv_img_src_t lv_img_src_get_type(const void * src)
|
||||
{
|
||||
lv_img_src_t img_src_type = LV_IMG_SRC_UNKNOWN;
|
||||
|
||||
if(src == NULL) return img_src_type;
|
||||
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) {
|
||||
img_src_type = LV_IMG_SRC_FILE; /*If it's an ASCII character then it's file name*/
|
||||
}
|
||||
else if(u8_p[0] >= 0x80) {
|
||||
img_src_type = LV_IMG_SRC_SYMBOL; /*Symbols begins after 0x7F*/
|
||||
}
|
||||
else {
|
||||
img_src_type = LV_IMG_SRC_VARIABLE; /*`lv_img_dsc_t` is draw to the first byte < 0x20*/
|
||||
}
|
||||
|
||||
if(LV_IMG_SRC_UNKNOWN == img_src_type) {
|
||||
LV_LOG_WARN("lv_img_src_get_type: unknown image type");
|
||||
}
|
||||
|
||||
return img_src_type;
|
||||
}
|
||||
|
||||
void lv_draw_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
|
||||
{
|
||||
if(draw_ctx->draw_img_decoded == NULL) return;
|
||||
|
||||
draw_ctx->draw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src)
|
||||
{
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return LV_RES_OK;
|
||||
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, draw_dsc->recolor, draw_dsc->frame_id);
|
||||
|
||||
if(cdsc == NULL) return LV_RES_INV;
|
||||
|
||||
|
||||
lv_img_cf_t cf;
|
||||
if(lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
else if(lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
else cf = LV_IMG_CF_TRUE_COLOR;
|
||||
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
|
||||
show_error(draw_ctx, coords, cdsc->dec_dsc.error_msg);
|
||||
}
|
||||
/*The decoder could open the image and gave the entire uncompressed image.
|
||||
*Just draw it!*/
|
||||
else if(cdsc->dec_dsc.img_data) {
|
||||
lv_area_t map_area_rot;
|
||||
lv_area_copy(&map_area_rot, coords);
|
||||
if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_img_buf_get_transformed_area(&map_area_rot, w, h, draw_dsc->angle, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
|
||||
map_area_rot.x1 += coords->x1;
|
||||
map_area_rot.y1 += coords->y1;
|
||||
map_area_rot.x2 += coords->x1;
|
||||
map_area_rot.y2 += coords->y1;
|
||||
}
|
||||
|
||||
lv_area_t clip_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&clip_com, draw_ctx->clip_area, &map_area_rot);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
draw_ctx->clip_area = &clip_com;
|
||||
lv_draw_img_decoded(draw_ctx, draw_dsc, coords, cdsc->dec_dsc.img_data, cf);
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
/*The whole uncompressed image is not available. Try to read it line-by-line*/
|
||||
else {
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, draw_ctx->clip_area, coords);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
int32_t width = lv_area_get_width(&mask_com);
|
||||
|
||||
uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) *
|
||||
LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
lv_area_t line;
|
||||
lv_area_copy(&line, &mask_com);
|
||||
lv_area_set_height(&line, 1);
|
||||
int32_t x = mask_com.x1 - coords->x1;
|
||||
int32_t y = mask_com.y1 - coords->y1;
|
||||
int32_t row;
|
||||
lv_res_t read_res;
|
||||
for(row = mask_com.y1; row <= mask_com.y2; row++) {
|
||||
lv_area_t mask_line;
|
||||
union_ok = _lv_area_intersect(&mask_line, clip_area_ori, &line);
|
||||
if(union_ok == false) continue;
|
||||
|
||||
read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf);
|
||||
if(read_res != LV_RES_OK) {
|
||||
lv_img_decoder_close(&cdsc->dec_dsc);
|
||||
LV_LOG_WARN("Image draw can't read the line");
|
||||
lv_mem_buf_release(buf);
|
||||
draw_cleanup(cdsc);
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
draw_ctx->clip_area = &mask_line;
|
||||
lv_draw_img_decoded(draw_ctx, draw_dsc, &line, buf, cf);
|
||||
line.y1++;
|
||||
line.y2++;
|
||||
y++;
|
||||
}
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
lv_mem_buf_release(buf);
|
||||
}
|
||||
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg)
|
||||
{
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_rect(draw_ctx, &rect_dsc, coords);
|
||||
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_draw_label(draw_ctx, &label_dsc, coords, msg, NULL);
|
||||
}
|
||||
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache)
|
||||
{
|
||||
/*Automatically close images with no caching*/
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(&cache->dec_dsc);
|
||||
#else
|
||||
LV_UNUSED(cache);
|
||||
#endif
|
||||
}
|
||||
104
LVGL.Simulator/lvgl/src/draw/lv_draw_img.h
Normal file
104
LVGL.Simulator/lvgl/src/draw/lv_draw_img.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @file lv_draw_img.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_IMG_H
|
||||
#define LV_DRAW_IMG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_img_buf.h"
|
||||
#include "../misc/lv_style.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
uint16_t angle;
|
||||
uint16_t zoom;
|
||||
lv_point_t pivot;
|
||||
|
||||
lv_color_t recolor;
|
||||
lv_opa_t recolor_opa;
|
||||
|
||||
lv_opa_t opa;
|
||||
lv_blend_mode_t blend_mode : 4;
|
||||
|
||||
int32_t frame_id;
|
||||
uint8_t antialias : 1;
|
||||
} lv_draw_img_dsc_t;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc);
|
||||
/**
|
||||
* Draw an image
|
||||
* @param coords the coordinates of the image
|
||||
* @param mask the image will be drawn only in this area
|
||||
* @param src pointer to a lv_color_t array which contains the pixels of the image
|
||||
* @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords,
|
||||
const void * src);
|
||||
|
||||
|
||||
void lv_draw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
* @param src pointer to an image source:
|
||||
* - pointer to an 'lv_img_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_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
|
||||
*/
|
||||
lv_img_src_t lv_img_src_get_type(const void * src);
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format is chroma keyed or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format has alpha channel or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_IMG_H*/
|
||||
417
LVGL.Simulator/lvgl/src/draw/lv_draw_label.c
Normal file
417
LVGL.Simulator/lvgl/src/draw/lv_draw_label.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* @file lv_draw_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_label.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_assert.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*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
enum {
|
||||
CMD_STATE_WAIT,
|
||||
CMD_STATE_PAR,
|
||||
CMD_STATE_IN,
|
||||
};
|
||||
typedef uint8_t cmd_state_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static uint8_t hex_char_to_num(char hex);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a text
|
||||
* @param coords coordinates of the label
|
||||
* @param mask the label will be drawn only in this area
|
||||
* @param dsc pointer to draw descriptor
|
||||
* @param txt `\0` terminated text to write
|
||||
* @param hint pointer to a `lv_draw_label_hint_t` variable.
|
||||
* It is managed by the draw to speed up the drawing of very long texts (thousands of lines).
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->font == NULL) {
|
||||
LV_LOG_WARN("dsc->font == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if(draw_ctx->draw_letter == NULL) {
|
||||
LV_LOG_WARN("draw->draw_letter == NULL (there is no function to draw letters)");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_label_dsc_t dsc_mod = *dsc;
|
||||
|
||||
const lv_font_t * font = dsc->font;
|
||||
int32_t w;
|
||||
|
||||
/*No need to waste processor time if string is empty*/
|
||||
if(txt == NULL || txt[0] == '\0')
|
||||
return;
|
||||
|
||||
lv_area_t clipped_area;
|
||||
bool clip_ok = _lv_area_intersect(&clipped_area, coords, draw_ctx->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, txt);
|
||||
|
||||
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_txt_get_size(&p, txt, 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;
|
||||
pos.x = coords->x1;
|
||||
pos.y = 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(hint && y_ofs == 0 && coords->y1 < 0) {
|
||||
/*If the label changed too much recalculate the hint.*/
|
||||
if(LV_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) {
|
||||
hint->line_start = -1;
|
||||
}
|
||||
last_line_start = hint->line_start;
|
||||
}
|
||||
|
||||
/*Use the hint if it's valid*/
|
||||
if(hint && last_line_start >= 0) {
|
||||
line_start = last_line_start;
|
||||
pos.y += hint->y;
|
||||
}
|
||||
|
||||
uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
|
||||
|
||||
/*Go the first visible line*/
|
||||
while(pos.y + line_height_font < draw_ctx->clip_area->y1) {
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag);
|
||||
pos.y += line_height;
|
||||
|
||||
/*Save at the threshold coordinate*/
|
||||
if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) {
|
||||
hint->line_start = line_start;
|
||||
hint->y = pos.y - coords->y1;
|
||||
hint->coord_y = coords->y1;
|
||||
}
|
||||
|
||||
if(txt[line_start] == '\0') return;
|
||||
}
|
||||
|
||||
/*Align to middle*/
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
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_draw_line_dsc_t line_dsc;
|
||||
|
||||
if((dsc->decor & LV_TEXT_DECOR_UNDERLINE) || (dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH)) {
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
line_dsc.color = dsc->color;
|
||||
line_dsc.width = font->underline_thickness ? font->underline_thickness : 1;
|
||||
line_dsc.opa = dsc->opa;
|
||||
line_dsc.blend_mode = dsc->blend_mode;
|
||||
}
|
||||
|
||||
cmd_state_t cmd_state = CMD_STATE_WAIT;
|
||||
uint32_t i;
|
||||
uint32_t par_start = 0;
|
||||
lv_color_t recolor;
|
||||
lv_color_t color = lv_color_black();
|
||||
int32_t letter_w;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc_sel;
|
||||
lv_draw_rect_dsc_init(&draw_dsc_sel);
|
||||
draw_dsc_sel.bg_color = dsc->sel_bg_color;
|
||||
|
||||
int32_t pos_x_start = pos.x;
|
||||
/*Write out all lines*/
|
||||
while(txt[line_start] != '\0') {
|
||||
pos.x += x_ofs;
|
||||
|
||||
/*Write all letter of a line*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = 0;
|
||||
#if LV_USE_BIDI
|
||||
char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1);
|
||||
_lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0);
|
||||
#else
|
||||
const char * bidi_txt = txt + 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_txt_encoded_get_char_id(txt, line_start);
|
||||
uint32_t t = _lv_txt_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_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
_lv_txt_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i);
|
||||
/*Handle the re-color command*/
|
||||
if((dsc->flag & LV_TEXT_FLAG_RECOLOR) != 0) {
|
||||
if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) {
|
||||
if(cmd_state == CMD_STATE_WAIT) { /*Start char*/
|
||||
par_start = i;
|
||||
cmd_state = CMD_STATE_PAR;
|
||||
continue;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_IN) { /*Command end*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*Skip the color parameter and wait the space after it*/
|
||||
if(cmd_state == CMD_STATE_PAR) {
|
||||
if(letter == ' ') {
|
||||
/*Get the parameter*/
|
||||
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
|
||||
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
|
||||
lv_memcpy_small(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
|
||||
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
|
||||
int r, g, b;
|
||||
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
|
||||
g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]);
|
||||
b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]);
|
||||
recolor = lv_color_make(r, g, b);
|
||||
}
|
||||
else {
|
||||
recolor.full = dsc->color.full;
|
||||
}
|
||||
cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
color = dsc->color;
|
||||
|
||||
if(cmd_state == CMD_STATE_IN) color = recolor;
|
||||
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
sel_coords.x2 = pos.x + letter_w + dsc->letter_space - 1;
|
||||
sel_coords.y2 = pos.y + line_height - 1;
|
||||
lv_draw_rect(draw_ctx, &draw_dsc_sel, &sel_coords);
|
||||
color = dsc->sel_color;
|
||||
}
|
||||
}
|
||||
|
||||
dsc_mod.color = color;
|
||||
lv_draw_letter(draw_ctx, &dsc_mod, &pos, letter);
|
||||
|
||||
if(letter_w > 0) {
|
||||
pos.x += letter_w + dsc->letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + (dsc->font->line_height / 2) + line_dsc.width / 2;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
line_dsc.color = color;
|
||||
lv_draw_line(draw_ctx, &line_dsc, &p1, &p2);
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + dsc->font->line_height - dsc->font->base_line - font->underline_position;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
line_dsc.color = color;
|
||||
lv_draw_line(draw_ctx, &line_dsc, &p1, &p2);
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
lv_mem_buf_release(bidi_txt);
|
||||
bidi_txt = NULL;
|
||||
#endif
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[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_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
|
||||
/*Go the next line position*/
|
||||
pos.y += line_height;
|
||||
|
||||
if(pos.y > draw_ctx->clip_area->y2) return;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
void lv_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter)
|
||||
{
|
||||
draw_ctx->draw_letter(draw_ctx, dsc, pos_p, letter);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Convert a hexadecimal characters to a number (0..15)
|
||||
* @param hex Pointer to a hexadecimal character (0..9, A..F)
|
||||
* @return the numerical value of `hex` or 0 on error
|
||||
*/
|
||||
static uint8_t hex_char_to_num(char hex)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
if(hex >= '0' && hex <= '9') {
|
||||
result = hex - '0';
|
||||
}
|
||||
else {
|
||||
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
|
||||
|
||||
switch(hex) {
|
||||
case 'A':
|
||||
result = 10;
|
||||
break;
|
||||
case 'B':
|
||||
result = 11;
|
||||
break;
|
||||
case 'C':
|
||||
result = 12;
|
||||
break;
|
||||
case 'D':
|
||||
result = 13;
|
||||
break;
|
||||
case 'E':
|
||||
result = 14;
|
||||
break;
|
||||
case 'F':
|
||||
result = 15;
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
100
LVGL.Simulator/lvgl/src/draw/lv_draw_label.h
Normal file
100
LVGL.Simulator/lvgl/src/draw/lv_draw_label.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @file lv_draw_label.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_LABEL_H
|
||||
#define LV_DRAW_LABEL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_txt.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_style.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
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;
|
||||
lv_coord_t line_space;
|
||||
lv_coord_t letter_space;
|
||||
lv_coord_t ofs_x;
|
||||
lv_coord_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;
|
||||
} lv_draw_label_dsc_t;
|
||||
|
||||
/** 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.*/
|
||||
typedef 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;
|
||||
} lv_draw_label_hint_t;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Write a text
|
||||
* @param coords coordinates of the label
|
||||
* @param mask the label will be drawn only in this area
|
||||
* @param dsc pointer to draw descriptor
|
||||
* @param txt `\0` terminated text to write
|
||||
* @param hint pointer to a `lv_draw_label_hint_t` variable.
|
||||
* It is managed by the draw to speed up the drawing of very long texts (thousands of lines).
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint);
|
||||
|
||||
void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LABEL_H*/
|
||||
56
LVGL.Simulator/lvgl/src/draw/lv_draw_line.c
Normal file
56
LVGL.Simulator/lvgl/src/draw/lv_draw_line.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file lv_draw_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_line_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc,
|
||||
const lv_point_t * point1, const lv_point_t * point2)
|
||||
{
|
||||
if(dsc->width == 0) return;
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_ctx->draw_line(draw_ctx, dsc, point1, point2);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
67
LVGL.Simulator/lvgl/src/draw/lv_draw_line.h
Normal file
67
LVGL.Simulator/lvgl/src/draw/lv_draw_line.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @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_color_t color;
|
||||
lv_coord_t width;
|
||||
lv_coord_t dash_width;
|
||||
lv_coord_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;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Draw a line
|
||||
* @param point1 first point of the line
|
||||
* @param point2 second point of the line
|
||||
* @param clip the line will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LINE_H*/
|
||||
1530
LVGL.Simulator/lvgl/src/draw/lv_draw_mask.c
Normal file
1530
LVGL.Simulator/lvgl/src/draw/lv_draw_mask.c
Normal file
File diff suppressed because it is too large
Load Diff
394
LVGL.Simulator/lvgl/src/draw/lv_draw_mask.h
Normal file
394
LVGL.Simulator/lvgl/src/draw/lv_draw_mask.h
Normal file
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
* @file lv_draw_mask.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_MASK_H
|
||||
#define LV_DRAW_MASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_MASK_ID_INV (-1)
|
||||
#if LV_DRAW_COMPLEX
|
||||
# define _LV_MASK_MAX_NUM 16
|
||||
#else
|
||||
# define _LV_MASK_MAX_NUM 1
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_RES_TRANSP,
|
||||
LV_DRAW_MASK_RES_FULL_COVER,
|
||||
LV_DRAW_MASK_RES_CHANGED,
|
||||
LV_DRAW_MASK_RES_UNKNOWN
|
||||
};
|
||||
|
||||
typedef uint8_t lv_draw_mask_res_t;
|
||||
|
||||
typedef struct {
|
||||
void * param;
|
||||
void * custom_id;
|
||||
} _lv_draw_mask_saved_t;
|
||||
|
||||
typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
|
||||
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX == 0
|
||||
static inline uint8_t lv_draw_mask_get_cnt(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool lv_draw_mask_is_any(const lv_area_t * a)
|
||||
{
|
||||
LV_UNUSED(a);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_TYPE_LINE,
|
||||
LV_DRAW_MASK_TYPE_ANGLE,
|
||||
LV_DRAW_MASK_TYPE_RADIUS,
|
||||
LV_DRAW_MASK_TYPE_FADE,
|
||||
LV_DRAW_MASK_TYPE_MAP,
|
||||
LV_DRAW_MASK_TYPE_POLYGON,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_draw_mask_type_t;
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT = 0,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT,
|
||||
LV_DRAW_MASK_LINE_SIDE_TOP,
|
||||
LV_DRAW_MASK_LINE_SIDE_BOTTOM,
|
||||
};
|
||||
|
||||
/**
|
||||
* A common callback type for every mask type.
|
||||
* Used internally by the library.
|
||||
*/
|
||||
typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len,
|
||||
void * p);
|
||||
|
||||
typedef uint8_t lv_draw_mask_line_side_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_mask_xcb_t cb;
|
||||
lv_draw_mask_type_t type;
|
||||
} _lv_draw_mask_common_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
/*First point*/
|
||||
lv_point_t p1;
|
||||
|
||||
/*Second point*/
|
||||
lv_point_t p2;
|
||||
|
||||
/*Which side to keep?*/
|
||||
lv_draw_mask_line_side_t side : 2;
|
||||
} cfg;
|
||||
|
||||
/*A point of the line*/
|
||||
lv_point_t origo;
|
||||
|
||||
/*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
|
||||
int32_t xy_steep;
|
||||
|
||||
/*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/
|
||||
int32_t yx_steep;
|
||||
|
||||
/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/
|
||||
int32_t steep;
|
||||
|
||||
/*Steepness in 1 px in 0..255 range. Used only by flat lines.*/
|
||||
int32_t spx;
|
||||
|
||||
/*1: It's a flat line? (Near to horizontal)*/
|
||||
uint8_t flat : 1;
|
||||
|
||||
/*Invert the mask. The default is: Keep the left part.
|
||||
*It is used to select left/right/top/bottom*/
|
||||
uint8_t inv: 1;
|
||||
} lv_draw_mask_line_param_t;
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_point_t vertex_p;
|
||||
lv_coord_t start_angle;
|
||||
lv_coord_t end_angle;
|
||||
} cfg;
|
||||
|
||||
lv_draw_mask_line_param_t start_line;
|
||||
lv_draw_mask_line_param_t end_line;
|
||||
uint16_t delta_deg;
|
||||
} lv_draw_mask_angle_param_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t * buf;
|
||||
lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/
|
||||
uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/
|
||||
uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/
|
||||
int32_t life; /*How many times the entry way used*/
|
||||
uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/
|
||||
lv_coord_t radius; /*The radius of the entry*/
|
||||
} _lv_draw_mask_radius_circle_dsc_t;
|
||||
|
||||
typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE];
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t rect;
|
||||
lv_coord_t radius;
|
||||
/*Invert the mask. 0: Keep the pixels inside.*/
|
||||
uint8_t outer: 1;
|
||||
} cfg;
|
||||
|
||||
_lv_draw_mask_radius_circle_dsc_t * circle;
|
||||
} lv_draw_mask_radius_param_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t coords;
|
||||
lv_coord_t y_top;
|
||||
lv_coord_t y_bottom;
|
||||
lv_opa_t opa_top;
|
||||
lv_opa_t opa_bottom;
|
||||
} cfg;
|
||||
|
||||
} lv_draw_mask_fade_param_t;
|
||||
|
||||
|
||||
typedef struct _lv_draw_mask_map_param_t {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t coords;
|
||||
const lv_opa_t * map;
|
||||
} cfg;
|
||||
} lv_draw_mask_map_param_t;
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_point_t * points;
|
||||
uint16_t point_cnt;
|
||||
} cfg;
|
||||
} lv_draw_mask_polygon_param_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask.
|
||||
* @param param an initialized mask parameter. Only the pointer is saved.
|
||||
* @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
|
||||
* @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
|
||||
*/
|
||||
int16_t lv_draw_mask_add(void * param, void * custom_id);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
* Apply the added buffers on a line. Used internally by the library's drawing routines.
|
||||
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
|
||||
* @param abs_x absolute X coordinate where the line to calculate start
|
||||
* @param abs_y absolute Y coordinate where the line to calculate start
|
||||
* @param len length of the line to calculate (in pixel count)
|
||||
* @return One of these values:
|
||||
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
|
||||
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
|
||||
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len);
|
||||
|
||||
/**
|
||||
* Apply the specified buffers on a line. Used internally by the library's drawing routines.
|
||||
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
|
||||
* @param abs_x absolute X coordinate where the line to calculate start
|
||||
* @param abs_y absolute Y coordinate where the line to calculate start
|
||||
* @param len length of the line to calculate (in pixel count)
|
||||
* @param ids ID array of added buffers
|
||||
* @param ids_count number of ID array
|
||||
* @return One of these values:
|
||||
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
|
||||
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
|
||||
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len, const int16_t * ids, int16_t ids_count);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
* Remove a mask with a given ID
|
||||
* @param id the ID of the mask. Returned by `lv_draw_mask_add`
|
||||
* @return the parameter of the removed mask.
|
||||
* If more masks have `custom_id` ID then the last mask's parameter will be returned
|
||||
*/
|
||||
void * lv_draw_mask_remove_id(int16_t id);
|
||||
|
||||
/**
|
||||
* Remove all mask with a given custom ID
|
||||
* @param custom_id a pointer used in `lv_draw_mask_add`
|
||||
* @return return the parameter of the removed mask.
|
||||
* If more masks have `custom_id` ID then the last mask's parameter will be returned
|
||||
*/
|
||||
void * lv_draw_mask_remove_custom(void * custom_id);
|
||||
|
||||
/**
|
||||
* Free the data from the parameter.
|
||||
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
|
||||
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
|
||||
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
|
||||
* @param p pointer to a mask parameter
|
||||
*/
|
||||
void lv_draw_mask_free_param(void * p);
|
||||
|
||||
/**
|
||||
* Called by LVGL the rendering of a screen is ready to clean up
|
||||
* the temporal (cache) data of the masks
|
||||
*/
|
||||
void _lv_draw_mask_cleanup(void);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
* Count the currently added masks
|
||||
* @return number of active masks
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
|
||||
|
||||
|
||||
/**
|
||||
* Check if there is any added draw mask
|
||||
* @param a an area to test for affecting masks.
|
||||
* @return true: there is t least 1 draw mask; false: there are no draw masks
|
||||
*/
|
||||
bool lv_draw_mask_is_any(const lv_area_t * a);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
*Initialize a line mask from two points.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param p1x X coordinate of the first point of the line
|
||||
* @param p1y Y coordinate of the first point of the line
|
||||
* @param p2x X coordinate of the second point of the line
|
||||
* @param p2y y coordinate of the second point of the line
|
||||
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
|
||||
*/
|
||||
void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x,
|
||||
lv_coord_t p2y, lv_draw_mask_line_side_t side);
|
||||
|
||||
/**
|
||||
*Initialize a line mask from a point and an angle.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param px X coordinate of a point of the line
|
||||
* @param py X coordinate of a point of the line
|
||||
* @param angle right 0 deg, bottom: 90
|
||||
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
|
||||
*/
|
||||
void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle,
|
||||
lv_draw_mask_line_side_t side);
|
||||
|
||||
/**
|
||||
* Initialize an angle mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param vertex_x X coordinate of the angle vertex (absolute coordinates)
|
||||
* @param vertex_y Y coordinate of the angle vertex (absolute coordinates)
|
||||
* @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
|
||||
* @param end_angle end angle
|
||||
*/
|
||||
void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y,
|
||||
lv_coord_t start_angle, lv_coord_t end_angle);
|
||||
|
||||
/**
|
||||
* Initialize a fade mask.
|
||||
* @param param pointer to an `lv_draw_mask_radius_param_t` to initialize
|
||||
* @param rect coordinates of the rectangle to affect (absolute coordinates)
|
||||
* @param radius radius of the rectangle
|
||||
* @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle
|
||||
*/
|
||||
void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv);
|
||||
|
||||
/**
|
||||
* Initialize a fade mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param coords coordinates of the area to affect (absolute coordinates)
|
||||
* @param opa_top opacity on the top
|
||||
* @param y_top at which coordinate start to change to opacity to `opa_bottom`
|
||||
* @param opa_bottom opacity at the bottom
|
||||
* @param y_bottom at which coordinate reach `opa_bottom`.
|
||||
*/
|
||||
void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top,
|
||||
lv_coord_t y_top,
|
||||
lv_opa_t opa_bottom, lv_coord_t y_bottom);
|
||||
|
||||
/**
|
||||
* Initialize a map mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param coords coordinates of the map (absolute coordinates)
|
||||
* @param map array of bytes with the mask values
|
||||
*/
|
||||
void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map);
|
||||
|
||||
void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt);
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_MASK_H*/
|
||||
73
LVGL.Simulator/lvgl/src/draw/lv_draw_rect.c
Normal file
73
LVGL.Simulator/lvgl/src/draw/lv_draw_rect.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file lv_draw_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_rect.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t));
|
||||
dsc->bg_color = lv_color_white();
|
||||
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_img_symbol_font = LV_FONT_DEFAULT;
|
||||
dsc->bg_opa = LV_OPA_COVER;
|
||||
dsc->bg_img_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a rectangle
|
||||
* @param coords the coordinates of the rectangle
|
||||
* @param mask the rectangle will be drawn only in this mask
|
||||
* @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return;
|
||||
|
||||
draw_ctx->draw_rect(draw_ctx, dsc, coords);
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
96
LVGL.Simulator/lvgl/src/draw/lv_draw_rect.h
Normal file
96
LVGL.Simulator/lvgl/src/draw/lv_draw_rect.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file lv_draw_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_RECT_H
|
||||
#define LV_DRAW_RECT_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"
|
||||
#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_coord_t radius;
|
||||
lv_blend_mode_t blend_mode;
|
||||
|
||||
/*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_img_src;
|
||||
const void * bg_img_symbol_font;
|
||||
lv_color_t bg_img_recolor;
|
||||
lv_opa_t bg_img_opa;
|
||||
lv_opa_t bg_img_recolor_opa;
|
||||
uint8_t bg_img_tiled;
|
||||
|
||||
/*Border*/
|
||||
lv_color_t border_color;
|
||||
lv_coord_t border_width;
|
||||
lv_opa_t border_opa;
|
||||
uint8_t border_post : 1; /*There is a border it will be drawn later.*/
|
||||
lv_border_side_t border_side : 5;
|
||||
|
||||
/*Outline*/
|
||||
lv_color_t outline_color;
|
||||
lv_coord_t outline_width;
|
||||
lv_coord_t outline_pad;
|
||||
lv_opa_t outline_opa;
|
||||
|
||||
/*Shadow*/
|
||||
lv_color_t shadow_color;
|
||||
lv_coord_t shadow_width;
|
||||
lv_coord_t shadow_ofs_x;
|
||||
lv_coord_t shadow_ofs_y;
|
||||
lv_coord_t shadow_spread;
|
||||
lv_opa_t shadow_opa;
|
||||
} lv_draw_rect_dsc_t;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
|
||||
/**
|
||||
* Draw a rectangle
|
||||
* @param coords the coordinates of the rectangle
|
||||
* @param clip the rectangle will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_RECT_H*/
|
||||
52
LVGL.Simulator/lvgl/src/draw/lv_draw_triangle.c
Normal file
52
LVGL.Simulator/lvgl/src/draw/lv_draw_triangle.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @file lv_draw_triangle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_triangle.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[],
|
||||
uint16_t point_cnt)
|
||||
{
|
||||
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, point_cnt);
|
||||
}
|
||||
|
||||
void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[])
|
||||
{
|
||||
|
||||
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 3);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
42
LVGL.Simulator/lvgl/src/draw/lv_draw_triangle.h
Normal file
42
LVGL.Simulator/lvgl/src/draw/lv_draw_triangle.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @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
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[],
|
||||
uint16_t point_cnt);
|
||||
|
||||
void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_TRIANGLE_H*/
|
||||
772
LVGL.Simulator/lvgl/src/draw/lv_img_buf.c
Normal file
772
LVGL.Simulator/lvgl/src/draw/lv_img_buf.c
Normal file
@@ -0,0 +1,772 @@
|
||||
/**
|
||||
* @file lv_img_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @param safe true: check out of bounds
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color)
|
||||
{
|
||||
lv_color_t p_color = lv_color_black();
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
#if LV_COLOR_SIZE == 32
|
||||
p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/
|
||||
#endif
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8, 16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2, 4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param safe true: check out of bounds
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
return buf_u8[px];
|
||||
}
|
||||
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8 ,12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c)
|
||||
{
|
||||
if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) ||
|
||||
(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) {
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(c);
|
||||
uint8_t * buf = (uint8_t *)dsc->data;
|
||||
lv_memcpy_small(&buf[id * sizeof(c32)], &c32, sizeof(c32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
/*Allocate image descriptor*/
|
||||
lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
lv_memset_00(dsc, sizeof(lv_img_dsc_t));
|
||||
|
||||
/*Get image data size*/
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*Allocate raw buffer*/
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
lv_memset_00((uint8_t *)dsc->data, dsc->data_size);
|
||||
|
||||
/*Fill in header*/
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t * dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free((void *)dsc->data);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Initialize a descriptor to transform an image
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
dsc->tmp.pivot_x_256 = dsc->cfg.pivot_x * 256;
|
||||
dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256;
|
||||
|
||||
int32_t angle_low = dsc->cfg.angle / 10;
|
||||
int32_t angle_high = angle_low + 1;
|
||||
int32_t angle_rem = dsc->cfg.angle - (angle_low * 10);
|
||||
|
||||
int32_t s1 = lv_trigo_sin(-angle_low);
|
||||
int32_t s2 = lv_trigo_sin(-angle_high);
|
||||
|
||||
int32_t c1 = lv_trigo_sin(-angle_low + 90);
|
||||
int32_t c2 = lv_trigo_sin(-angle_high + 90);
|
||||
|
||||
dsc->tmp.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10;
|
||||
dsc->tmp.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10;
|
||||
|
||||
/*Use smaller value to avoid overflow*/
|
||||
dsc->tmp.sinma = dsc->tmp.sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
dsc->tmp.cosma = dsc->tmp.cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
|
||||
dsc->tmp.chroma_keyed = lv_img_cf_is_chroma_keyed(dsc->cfg.cf) ? 1 : 0;
|
||||
dsc->tmp.has_alpha = lv_img_cf_has_alpha(dsc->cfg.cf) ? 1 : 0;
|
||||
if(dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
dsc->tmp.native_color = 1;
|
||||
}
|
||||
else {
|
||||
dsc->tmp.native_color = 0;
|
||||
}
|
||||
|
||||
dsc->tmp.img_dsc.data = dsc->cfg.src;
|
||||
dsc->tmp.img_dsc.header.always_zero = 0;
|
||||
dsc->tmp.img_dsc.header.cf = dsc->cfg.cf;
|
||||
dsc->tmp.img_dsc.header.w = dsc->cfg.src_w;
|
||||
dsc->tmp.img_dsc.header.h = dsc->cfg.src_h;
|
||||
|
||||
/*The inverse of the zoom will be sued during the transformation
|
||||
* + dsc->cfg.zoom / 2 for rounding*/
|
||||
dsc->tmp.zoom_inv = (((256 * 256) << _LV_ZOOM_INV_UPSCALE) + dsc->cfg.zoom / 2) / dsc->cfg.zoom;
|
||||
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
dsc->res.color = dsc->cfg.color;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the area of a rectangle if its rotated and scaled
|
||||
* @param res store the coordinates here
|
||||
* @param w width of the rectangle to transform
|
||||
* @param h height of the rectangle to transform
|
||||
* @param angle angle of rotation
|
||||
* @param zoom zoom, (256 no zoom)
|
||||
* @param pivot x,y pivot coordinates of rotation
|
||||
*/
|
||||
void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
|
||||
const lv_point_t * pivot)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) {
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
res->x1 = (((int32_t)(-pivot->x) * zoom) >> 8) - 1;
|
||||
res->y1 = (((int32_t)(-pivot->y) * zoom) >> 8) - 1;
|
||||
res->x2 = (((int32_t)(w - pivot->x) * zoom) >> 8) + 2;
|
||||
res->y2 = (((int32_t)(h - pivot->y) * zoom) >> 8) + 2;
|
||||
|
||||
if(angle == 0) {
|
||||
res->x1 += pivot->x;
|
||||
res->y1 += pivot->y;
|
||||
res->x2 += pivot->x;
|
||||
res->y2 += pivot->y;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t angle_low = angle / 10;
|
||||
int32_t angle_high = angle_low + 1;
|
||||
int32_t angle_rem = angle - (angle_low * 10);
|
||||
|
||||
int32_t s1 = lv_trigo_sin(angle_low);
|
||||
int32_t s2 = lv_trigo_sin(angle_high);
|
||||
|
||||
int32_t c1 = lv_trigo_sin(angle_low + 90);
|
||||
int32_t c2 = lv_trigo_sin(angle_high + 90);
|
||||
|
||||
int32_t sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10;
|
||||
int32_t cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10;
|
||||
|
||||
/*Use smaller value to avoid overflow*/
|
||||
sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
|
||||
lv_point_t lt;
|
||||
lv_point_t rt;
|
||||
lv_point_t lb;
|
||||
lv_point_t rb;
|
||||
|
||||
lv_coord_t xt;
|
||||
lv_coord_t yt;
|
||||
|
||||
xt = res->x1;
|
||||
yt = res->y1;
|
||||
lt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
lt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x2;
|
||||
yt = res->y1;
|
||||
rt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
rt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x1;
|
||||
yt = res->y2;
|
||||
lb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
lb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x2;
|
||||
yt = res->y2;
|
||||
rb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
rb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
res->x1 = LV_MIN4(lb.x, lt.x, rb.x, rt.x);
|
||||
res->x2 = LV_MAX4(lb.x, lt.x, rb.x, rt.x);
|
||||
res->y1 = LV_MIN4(lb.y, lt.y, rb.y, rt.y);
|
||||
res->y2 = LV_MAX4(lb.y, lt.y, rb.y, rt.y);
|
||||
#else
|
||||
LV_UNUSED(angle);
|
||||
LV_UNUSED(zoom);
|
||||
LV_UNUSED(pivot);
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Get which color and opa would come to a pixel if it were rotated
|
||||
* @param dsc a descriptor initialized by `lv_img_buf_rotate_init`
|
||||
* @param x the coordinate which color and opa should be get
|
||||
* @param y the coordinate which color and opa should be get
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
const uint8_t * src_u8 = (const uint8_t *)dsc->cfg.src;
|
||||
|
||||
/*Get the target point relative coordinates to the pivot*/
|
||||
int32_t xt = x - dsc->cfg.pivot_x;
|
||||
int32_t yt = y - dsc->cfg.pivot_y;
|
||||
|
||||
int32_t xs;
|
||||
int32_t ys;
|
||||
if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) {
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
else if(dsc->cfg.angle == 0) {
|
||||
xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
xs = xt + dsc->tmp.pivot_x_256;
|
||||
ys = yt + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
else {
|
||||
xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
|
||||
/*Get the integer part of the source pixel*/
|
||||
int32_t xs_int = xs >> 8;
|
||||
int32_t ys_int = ys >> 8;
|
||||
|
||||
if(xs_int >= dsc->cfg.src_w) return false;
|
||||
else if(xs_int < 0) return false;
|
||||
|
||||
if(ys_int >= dsc->cfg.src_h) return false;
|
||||
else if(ys_int < 0) return false;
|
||||
|
||||
uint8_t px_size;
|
||||
uint32_t pxi;
|
||||
if(dsc->tmp.native_color) {
|
||||
if(dsc->tmp.has_alpha == 0) {
|
||||
px_size = LV_COLOR_SIZE >> 3;
|
||||
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size);
|
||||
}
|
||||
else {
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1);
|
||||
dsc->res.opa = src_u8[pxi + px_size - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
pxi = 0; /*unused*/
|
||||
px_size = 0; /*unused*/
|
||||
dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color);
|
||||
dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int);
|
||||
}
|
||||
|
||||
if(dsc->tmp.chroma_keyed) {
|
||||
lv_color_t ct = LV_COLOR_CHROMA_KEY;
|
||||
if(dsc->res.color.full == ct.full) return false;
|
||||
}
|
||||
|
||||
if(dsc->cfg.antialias == false) return true;
|
||||
|
||||
dsc->tmp.xs = xs;
|
||||
dsc->tmp.ys = ys;
|
||||
dsc->tmp.xs_int = xs_int;
|
||||
dsc->tmp.ys_int = ys_int;
|
||||
dsc->tmp.pxi = pxi;
|
||||
dsc->tmp.px_size = px_size;
|
||||
|
||||
bool ret;
|
||||
ret = _lv_img_buf_transform_anti_alias(dsc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue transformation by taking the neighbors into account
|
||||
* @param dsc pointer to the transformation descriptor
|
||||
*/
|
||||
bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
const uint8_t * src_u8 = dsc->cfg.src;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = dsc->tmp.xs & 0xff;
|
||||
int ys_fract = dsc->tmp.ys & 0xff;
|
||||
int32_t xn; /*x neighbor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
|
||||
if(xs_fract < 0x70) {
|
||||
xn = - 1;
|
||||
if(dsc->tmp.xs_int + xn < 0) xn = 0;
|
||||
xr = xs_fract + 0x80;
|
||||
}
|
||||
else if(xs_fract > 0x90) {
|
||||
xn = 1;
|
||||
if(dsc->tmp.xs_int + xn >= dsc->cfg.src_w) xn = 0;
|
||||
xr = (0xFF - xs_fract) + 0x80;
|
||||
}
|
||||
else {
|
||||
xn = 0;
|
||||
xr = 0xFF;
|
||||
}
|
||||
|
||||
int32_t yn; /*x neighbor*/
|
||||
lv_opa_t yr; /*x mix ratio*/
|
||||
|
||||
if(ys_fract < 0x70) {
|
||||
yn = - 1;
|
||||
if(dsc->tmp.ys_int + yn < 0) yn = 0;
|
||||
|
||||
yr = ys_fract + 0x80;
|
||||
}
|
||||
else if(ys_fract > 0x90) {
|
||||
yn = 1;
|
||||
if(dsc->tmp.ys_int + yn >= dsc->cfg.src_h) yn = 0;
|
||||
|
||||
yr = (0xFF - ys_fract) + 0x80;
|
||||
}
|
||||
else {
|
||||
yn = 0;
|
||||
yr = 0xFF;
|
||||
}
|
||||
|
||||
lv_color_t c00 = dsc->res.color;
|
||||
lv_color_t c01;
|
||||
lv_color_t c10;
|
||||
lv_color_t c11;
|
||||
|
||||
lv_opa_t a00 = dsc->res.opa;
|
||||
lv_opa_t a10 = 0;
|
||||
lv_opa_t a01 = 0;
|
||||
lv_opa_t a11 = 0;
|
||||
|
||||
if(dsc->tmp.native_color) {
|
||||
lv_memcpy_small(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t));
|
||||
lv_memcpy_small(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t));
|
||||
lv_memcpy_small(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn],
|
||||
sizeof(lv_color_t));
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1];
|
||||
a11 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
c01 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int, dsc->cfg.color);
|
||||
c10 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
c11 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int);
|
||||
a01 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn);
|
||||
a11 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn);
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t xr0 = xr;
|
||||
lv_opa_t xr1 = xr;
|
||||
if(dsc->tmp.has_alpha) {
|
||||
lv_opa_t a0 = (a00 * xr + (a10 * (255 - xr))) >> 8;
|
||||
lv_opa_t a1 = (a01 * xr + (a11 * (255 - xr))) >> 8;
|
||||
dsc->res.opa = (a0 * yr + (a1 * (255 - yr))) >> 8;
|
||||
|
||||
if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false;
|
||||
if(a0 <= LV_OPA_MIN) yr = LV_OPA_TRANSP;
|
||||
if(a1 <= LV_OPA_MIN) yr = LV_OPA_COVER;
|
||||
if(a00 <= LV_OPA_MIN) xr0 = LV_OPA_TRANSP;
|
||||
if(a10 <= LV_OPA_MIN) xr0 = LV_OPA_COVER;
|
||||
if(a01 <= LV_OPA_MIN) xr1 = LV_OPA_TRANSP;
|
||||
if(a11 <= LV_OPA_MIN) xr1 = LV_OPA_COVER;
|
||||
}
|
||||
else {
|
||||
xr0 = xr;
|
||||
xr1 = xr;
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
lv_color_t c0;
|
||||
if(xr0 == LV_OPA_TRANSP) c0 = c01;
|
||||
else if(xr0 == LV_OPA_COVER) c0 = c00;
|
||||
else c0 = lv_color_mix(c00, c01, xr0);
|
||||
|
||||
lv_color_t c1;
|
||||
if(xr1 == LV_OPA_TRANSP) c1 = c11;
|
||||
else if(xr1 == LV_OPA_COVER) c1 = c10;
|
||||
else c1 = lv_color_mix(c10, c11, xr1);
|
||||
|
||||
if(yr == LV_OPA_TRANSP) dsc->res.color = c1;
|
||||
else if(yr == LV_OPA_COVER) dsc->res.color = c0;
|
||||
else dsc->res.color = lv_color_mix(c0, c1, yr);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
310
LVGL.Simulator/lvgl/src/draw/lv_img_buf.h
Normal file
310
LVGL.Simulator/lvgl/src/draw/lv_img_buf.h
Normal file
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @file lv_img_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_BUF_H
|
||||
#define LV_IMG_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*If image pixels contains alpha we need to know how much byte is a pixel*/
|
||||
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 2
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 3
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 4
|
||||
#endif
|
||||
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
|
||||
#define _LV_TRANSFORM_TRIGO_SHIFT 10
|
||||
#define _LV_ZOOM_INV_UPSCALE 5
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Image color format*/
|
||||
enum {
|
||||
LV_IMG_CF_UNKNOWN = 0,
|
||||
|
||||
LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/
|
||||
LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder
|
||||
function*/
|
||||
LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
|
||||
custom decoder function*/
|
||||
|
||||
LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/
|
||||
LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
|
||||
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
|
||||
will be transparent*/
|
||||
|
||||
LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (can't be chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (can't be chroma keyed)*/
|
||||
|
||||
LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
|
||||
LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
|
||||
|
||||
LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_18, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_19, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_20, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_21, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_22, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_23, /**< Reserved for further use.*/
|
||||
|
||||
LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format.*/
|
||||
};
|
||||
typedef uint8_t lv_img_cf_t;
|
||||
|
||||
|
||||
/**
|
||||
* The first 8 bit is very important to distinguish the different source types.
|
||||
* For more info see `lv_img_get_src_type()` in lv_img.c
|
||||
* On big endian systems the order is reversed so cf and always_zero must be at
|
||||
* the end of the struct.
|
||||
*/
|
||||
#if LV_BIG_ENDIAN_SYSTEM
|
||||
typedef struct {
|
||||
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
|
||||
|
||||
} lv_img_header_t;
|
||||
#else
|
||||
typedef struct {
|
||||
|
||||
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
} lv_img_header_t;
|
||||
#endif
|
||||
|
||||
/** Image header it is compatible with
|
||||
* the result from image converter utility*/
|
||||
typedef struct {
|
||||
lv_img_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*/
|
||||
} lv_img_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
const void * src; /*image source (array of pixels)*/
|
||||
lv_coord_t src_w; /*width of the image source*/
|
||||
lv_coord_t src_h; /*height of the image source*/
|
||||
lv_coord_t pivot_x; /*pivot x*/
|
||||
lv_coord_t pivot_y; /*pivot y*/
|
||||
int16_t angle; /*angle to rotate*/
|
||||
uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/
|
||||
lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/
|
||||
lv_img_cf_t cf; /*color format of the image to rotate*/
|
||||
bool antialias;
|
||||
} cfg;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
} res;
|
||||
|
||||
struct {
|
||||
lv_img_dsc_t img_dsc;
|
||||
int32_t pivot_x_256;
|
||||
int32_t pivot_y_256;
|
||||
int32_t sinma;
|
||||
int32_t cosma;
|
||||
|
||||
uint8_t chroma_keyed : 1;
|
||||
uint8_t has_alpha : 1;
|
||||
uint8_t native_color : 1;
|
||||
|
||||
uint32_t zoom_inv;
|
||||
|
||||
/*Runtime data*/
|
||||
lv_coord_t xs;
|
||||
lv_coord_t ys;
|
||||
lv_coord_t xs_int;
|
||||
lv_coord_t ys_int;
|
||||
uint32_t pxi;
|
||||
uint8_t px_size;
|
||||
} tmp;
|
||||
} lv_img_transform_dsc_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @param safe true: check out of bounds
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param safe true: check out of bounds
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Initialize a descriptor to rotate an image
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Continue transformation by taking the neighbors into account
|
||||
* @param dsc pointer to the transformation descriptor
|
||||
*/
|
||||
bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get which color and opa would come to a pixel if it were rotated
|
||||
* @param dsc a descriptor initialized by `lv_img_buf_rotate_init`
|
||||
* @param x the coordinate which color and opa should be get
|
||||
* @param y the coordinate which color and opa should be get
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Get the area of a rectangle if its rotated and scaled
|
||||
* @param res store the coordinates here
|
||||
* @param w width of the rectangle to transform
|
||||
* @param h height of the rectangle to transform
|
||||
* @param angle angle of rotation
|
||||
* @param zoom zoom, (256 no zoom)
|
||||
* @param pivot x,y pivot coordinates of rotation
|
||||
*/
|
||||
void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
|
||||
const lv_point_t * pivot);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_BUF_H*/
|
||||
215
LVGL.Simulator/lvgl/src/draw/lv_img_cache.c
Normal file
215
LVGL.Simulator/lvgl/src/draw/lv_img_cache.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @file lv_img_cache.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
#define LV_IMG_CACHE_LIFE_GAIN 1
|
||||
|
||||
/*Don't let life to be greater than this limit because it would require a lot of time to
|
||||
* "die" from very high values*/
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
_lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
/*Decrement all lifes. Make the entries older*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
|
||||
cache[i].life -= LV_IMG_CACHE_AGING;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(color.full == cache[i].dec_dsc.color.full &&
|
||||
frame_id == cache[i].dec_dsc.frame_id &&
|
||||
lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
/*If opened increment its life.
|
||||
*Image difficult to open should live longer to keep avoid frequent their recaching.
|
||||
*Therefore increase `life` with `time_to_open`*/
|
||||
cached_src = &cache[i];
|
||||
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
|
||||
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
|
||||
LV_LOG_TRACE("image source found in the cache");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
if(cached_src) return cached_src;
|
||||
|
||||
/*Find an entry to reuse. Select the entry with the least life*/
|
||||
cached_src = &cache[0];
|
||||
for(i = 1; i < entry_cnt; i++) {
|
||||
if(cache[i].life < cached_src->life) {
|
||||
cached_src = &cache[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*Close the decoder to reuse if it was opened (has a valid source)*/
|
||||
if(cached_src->dec_dsc.src) {
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
|
||||
}
|
||||
else {
|
||||
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
|
||||
}
|
||||
#else
|
||||
cached_src = &LV_GC_ROOT(_lv_img_cache_single);
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start = lv_tick_get();
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_memset_00(cached_src, sizeof(_lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cached_src->life = 0;
|
||||
|
||||
/*If `time_to_open` was not set in the open function set it here*/
|
||||
if(cached_src->dec_dsc.time_to_open == 0) {
|
||||
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
|
||||
}
|
||||
|
||||
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
|
||||
|
||||
return cached_src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
{
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
LV_UNUSED(new_entry_cnt);
|
||||
LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0");
|
||||
#else
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
lv_mem_free(LV_GC_ROOT(_lv_img_cache_array));
|
||||
}
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt);
|
||||
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
}
|
||||
entry_cnt = new_entry_cnt;
|
||||
|
||||
/*Clean the cache*/
|
||||
lv_memset_00(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src)
|
||||
{
|
||||
LV_UNUSED(src);
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
if(cache[i].dec_dsc.src != NULL) {
|
||||
lv_img_decoder_close(&cache[i].dec_dsc);
|
||||
}
|
||||
|
||||
lv_memset_00(&cache[i], sizeof(_lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src1);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE)
|
||||
return src1 == src2;
|
||||
if(src_type != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
return strcmp(src1, src2) == 0;
|
||||
}
|
||||
#endif
|
||||
78
LVGL.Simulator/lvgl/src/draw/lv_img_cache.h
Normal file
78
LVGL.Simulator/lvgl/src/draw/lv_img_cache.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_img_cache.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_CACHE_H
|
||||
#define LV_IMG_CACHE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* When loading images from the network it can take a long time to download and decode the image.
|
||||
*
|
||||
* To avoid repeating this heavy load images can be cached.
|
||||
*/
|
||||
typedef struct {
|
||||
lv_img_decoder_dsc_t dec_dsc; /**< Image information*/
|
||||
|
||||
/** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used.
|
||||
* Decrement all lifes by one every in every ::lv_img_cache_open.
|
||||
* If life == 0 the entry can be reused*/
|
||||
int32_t life;
|
||||
} _lv_img_cache_entry_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id);
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_slot_num);
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_CACHE_H*/
|
||||
704
LVGL.Simulator/lvgl/src/draw/lv_img_decoder.c
Normal file
704
LVGL.Simulator/lvgl/src/draw/lv_img_decoder.c
Normal file
@@ -0,0 +1,704 @@
|
||||
/**
|
||||
* @file lv_img_decoder.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw_img.h"
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR
|
||||
#define CF_BUILT_IN_LAST LV_IMG_CF_ALPHA_8BIT
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_fs_file_t f;
|
||||
lv_color_t * palette;
|
||||
lv_opa_t * opa;
|
||||
} lv_img_decoder_built_in_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the image decoder module
|
||||
*/
|
||||
void _lv_img_decoder_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_img_decoder_ll), sizeof(lv_img_decoder_t));
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
|
||||
/*Create a decoder for the built in color format*/
|
||||
decoder = lv_img_decoder_create();
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_init: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_img_decoder_set_info_cb(decoder, lv_img_decoder_built_in_info);
|
||||
lv_img_decoder_set_open_cb(decoder, lv_img_decoder_built_in_open);
|
||||
lv_img_decoder_set_read_line_cb(decoder, lv_img_decoder_built_in_read_line);
|
||||
lv_img_decoder_set_close_cb(decoder, lv_img_decoder_built_in_close);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. E.g. file name or variable.
|
||||
* @param header the image info will be stored here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image
|
||||
*/
|
||||
lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header)
|
||||
{
|
||||
lv_memset_00(header, sizeof(lv_img_header_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
lv_img_decoder_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), d) {
|
||||
if(d->info_cb) {
|
||||
res = d->info_cb(d, src, header);
|
||||
if(res == LV_RES_OK) break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
dsc->color = color;
|
||||
dsc->src_type = src_type;
|
||||
dsc->frame_id = frame_id;
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
size_t fnlen = strlen(src);
|
||||
dsc->src = lv_mem_alloc(fnlen + 1);
|
||||
LV_ASSERT_MALLOC(dsc->src);
|
||||
if(dsc->src == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
strcpy((char *)dsc->src, src);
|
||||
}
|
||||
else {
|
||||
dsc->src = src;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), decoder) {
|
||||
/*Info and Open callbacks are required*/
|
||||
if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue;
|
||||
|
||||
res = decoder->info_cb(decoder, src, &dsc->header);
|
||||
if(res != LV_RES_OK) continue;
|
||||
|
||||
dsc->decoder = decoder;
|
||||
res = decoder->open_cb(decoder, dsc);
|
||||
|
||||
/*Opened successfully. It is a good decoder for this image source*/
|
||||
if(res == LV_RES_OK) return res;
|
||||
|
||||
/*Prepare for the next loop*/
|
||||
lv_memset_00(&dsc->header, sizeof(lv_img_header_t));
|
||||
|
||||
dsc->error_msg = NULL;
|
||||
dsc->img_data = NULL;
|
||||
dsc->user_data = NULL;
|
||||
dsc->time_to_open = 0;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE)
|
||||
lv_mem_free((void *)dsc->src);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line from an opened image
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
* @param x start X coordinate (from left)
|
||||
* @param y start Y coordinate (from top)
|
||||
* @param len number of pixels to read
|
||||
* @param buf store the data here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: an error occurred
|
||||
*/
|
||||
lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
lv_res_t res = LV_RES_INV;
|
||||
if(dsc->decoder->read_line_cb) res = dsc->decoder->read_line_cb(dsc->decoder, dsc, x, y, len, buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a decoding session
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
*/
|
||||
void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->decoder) {
|
||||
if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc);
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_mem_free((void *)dsc->src);
|
||||
dsc->src = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image decoder
|
||||
* @return pointer to the new image decoder
|
||||
*/
|
||||
lv_img_decoder_t * lv_img_decoder_create(void)
|
||||
{
|
||||
lv_img_decoder_t * decoder;
|
||||
decoder = _lv_ll_ins_head(&LV_GC_ROOT(_lv_img_decoder_ll));
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) return NULL;
|
||||
|
||||
lv_memset_00(decoder, sizeof(lv_img_decoder_t));
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an image decoder
|
||||
* @param decoder pointer to an image decoder
|
||||
*/
|
||||
void lv_img_decoder_delete(lv_img_decoder_t * decoder)
|
||||
{
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_img_decoder_ll), decoder);
|
||||
lv_mem_free(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_img_header_t` struct)
|
||||
*/
|
||||
void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb)
|
||||
{
|
||||
decoder->info_cb = 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_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb)
|
||||
{
|
||||
decoder->open_cb = 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_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb)
|
||||
{
|
||||
decoder->read_line_cb = 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_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb)
|
||||
{
|
||||
decoder->close_cb = close_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about a built-in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol
|
||||
* @param header store the image data here
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
|
||||
header->w = ((lv_img_dsc_t *)src)->header.w;
|
||||
header->h = ((lv_img_dsc_t *)src)->header.h;
|
||||
header->cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
|
||||
if(res == LV_FS_RES_OK) {
|
||||
uint32_t rn;
|
||||
res = lv_fs_read(&f, header, sizeof(lv_img_header_t), &rn);
|
||||
lv_fs_close(&f);
|
||||
if(res != LV_FS_RES_OK || rn != sizeof(lv_img_header_t)) {
|
||||
LV_LOG_WARN("Image get info get read file header");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
if(header->cf < CF_BUILT_IN_FIRST || header->cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
/*The size depend on the font but it is unknown here. It should be handled outside of the
|
||||
*function*/
|
||||
header->w = 1;
|
||||
header->h = 1;
|
||||
/*Symbols always have transparent parts. Important because of cover check in the draw
|
||||
*function. The actual value doesn't matter because lv_draw_label will draw it*/
|
||||
header->cf = LV_IMG_CF_ALPHA_1BIT;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Image get info found unknown src type");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a built in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it.
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
/*Open the file if it's a file*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, dsc->src, LV_FS_MODE_RD);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder can't open the file");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*If the file was open successfully save the file descriptor*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_fs_close(&f);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_memcpy_small(&user_data->f, &f, sizeof(f));
|
||||
}
|
||||
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*The variables should have valid data*/
|
||||
if(((lv_img_dsc_t *)dsc->src)->data == NULL) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
lv_img_cf_t cf = dsc->header.cf;
|
||||
/*Process true color formats*/
|
||||
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
||||
*So simply give its pointer*/
|
||||
dsc->img_data = ((lv_img_dsc_t *)dsc->src)->data;
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
/*If it's a file it need to be read line by line later*/
|
||||
return LV_RES_OK;
|
||||
}
|
||||
}
|
||||
/*Process indexed images. Build a palette*/
|
||||
else if(cf == LV_IMG_CF_INDEXED_1BIT || cf == LV_IMG_CF_INDEXED_2BIT || cf == LV_IMG_CF_INDEXED_4BIT ||
|
||||
cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(cf);
|
||||
uint32_t palette_size = 1 << px_size;
|
||||
|
||||
/*Allocate the palette*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
user_data->palette = lv_mem_alloc(palette_size * sizeof(lv_color_t));
|
||||
LV_ASSERT_MALLOC(user_data->palette);
|
||||
user_data->opa = lv_mem_alloc(palette_size * sizeof(lv_opa_t));
|
||||
LV_ASSERT_MALLOC(user_data->opa);
|
||||
if(user_data->palette == NULL || user_data->opa == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Read the palette from file*/
|
||||
lv_fs_seek(&user_data->f, 4, LV_FS_SEEK_SET); /*Skip the header*/
|
||||
lv_color32_t cur_color;
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
lv_fs_read(&user_data->f, &cur_color, sizeof(lv_color32_t), NULL);
|
||||
user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue);
|
||||
user_data->opa[i] = cur_color.ch.alpha;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*The palette begins in the beginning of the image data. Just point to it.*/
|
||||
lv_color32_t * palette_p = (lv_color32_t *)((lv_img_dsc_t *)dsc->src)->data;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
user_data->palette[i] = lv_color_make(palette_p[i].ch.red, palette_p[i].ch.green, palette_p[i].ch.blue);
|
||||
user_data->opa[i] = palette_p[i].ch.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
/*Alpha indexed images.*/
|
||||
else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT ||
|
||||
cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
return LV_RES_OK; /*Nothing to process*/
|
||||
}
|
||||
/*Unknown format. Can't decode it.*/
|
||||
else {
|
||||
/*Free the potentially allocated memories*/
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
|
||||
LV_LOG_WARN("Image decoder open: unknown color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* Required only if the "open" function can't return with the whole decoded pixel array.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
* @param x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
|
||||
lv_coord_t y, lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
/*For TRUE_COLOR images read line required only for files.
|
||||
*For variables the image data was returned in `open`*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
res = lv_img_decoder_built_in_line_true_color(dsc, x, y, len, buf);
|
||||
}
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_alpha(dsc, x, y, len, buf);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT || dsc->header.cf == LV_IMG_CF_INDEXED_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_INDEXED_4BIT || dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_indexed(dsc, x, y, len, buf);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Built-in image decoder read not supports the color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the pending decoding. Free resources etc.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
*/
|
||||
void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
if(user_data) {
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_fs_close(&user_data->f);
|
||||
}
|
||||
if(user_data->palette) lv_mem_free(user_data->palette);
|
||||
if(user_data->opa) lv_mem_free(user_data->opa);
|
||||
|
||||
lv_mem_free(user_data);
|
||||
dsc->user_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_fs_res_t res;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
|
||||
uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3;
|
||||
pos += 4; /*Skip the header*/
|
||||
res = lv_fs_seek(&user_data->f, pos, LV_FS_SEEK_SET);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder seek failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
uint32_t btr = len * (px_size >> 3);
|
||||
uint32_t br = 0;
|
||||
res = lv_fs_read(&user_data->f, buf, btr, &br);
|
||||
if(res != LV_FS_RES_OK || btr != br) {
|
||||
LV_LOG_WARN("Built-in image decoder read failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
const lv_opa_t alpha1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
|
||||
const lv_opa_t alpha2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
const lv_opa_t alpha4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
/*Simply fill the buffer with the color. Later only the alpha value will be modified.*/
|
||||
lv_color_t bg_color = dsc->color;
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (bg_color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = bg_color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
const lv_opa_t * opa_table = NULL;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
uint32_t ofs = 0;
|
||||
int8_t pos = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
pos = 7 - (x & 0x7);
|
||||
opa_table = alpha1_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
opa_table = alpha2_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
opa_table = alpha4_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] =
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_8BIT ? val_act : opa_table[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
int8_t pos = 0;
|
||||
uint32_t ofs = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
ofs += 8; /*Skip the palette*/
|
||||
pos = 7 - (x & 0x7);
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
ofs += 16; /*Skip the palette*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
ofs += 64; /*Skip the palette*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
ofs += 1024; /*Skip the palette*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
lv_color_t color = user_data->palette[val_act];
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = user_data->opa[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
274
LVGL.Simulator/lvgl/src/draw/lv_img_decoder.h
Normal file
274
LVGL.Simulator/lvgl/src/draw/lv_img_decoder.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @file lv_img_decoder.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_DECODER_H
|
||||
#define LV_IMG_DECODER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "../misc/lv_fs.h"
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Source of image.*/
|
||||
enum {
|
||||
LV_IMG_SRC_VARIABLE, /** Binary/C variable*/
|
||||
LV_IMG_SRC_FILE, /** File in filesystem*/
|
||||
LV_IMG_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/
|
||||
LV_IMG_SRC_UNKNOWN, /** Unknown source*/
|
||||
};
|
||||
|
||||
typedef uint8_t lv_img_src_t;
|
||||
|
||||
/*Decoder function definitions*/
|
||||
struct _lv_img_decoder_dsc_t;
|
||||
struct _lv_img_decoder_t;
|
||||
|
||||
/**
|
||||
* Get info from an image and store in the `header`
|
||||
* @param src the image source. Can be a pointer to a C array or a file name (Use
|
||||
* `lv_img_src_get_type` to determine the type)
|
||||
* @param header store the info here
|
||||
* @return LV_RES_OK: info written correctly; LV_RES_INV: failed
|
||||
*/
|
||||
typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder_t * decoder, const void * src,
|
||||
lv_img_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_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* 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 x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
typedef lv_res_t (*lv_img_decoder_read_line_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc,
|
||||
lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**
|
||||
* 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_img_decoder_close_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
|
||||
typedef struct _lv_img_decoder_t {
|
||||
lv_img_decoder_info_f_t info_cb;
|
||||
lv_img_decoder_open_f_t open_cb;
|
||||
lv_img_decoder_read_line_f_t read_line_cb;
|
||||
lv_img_decoder_close_f_t close_cb;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
} lv_img_decoder_t;
|
||||
|
||||
|
||||
/**Describe an image decoding session. Stores data about the decoding*/
|
||||
typedef struct _lv_img_decoder_dsc_t {
|
||||
/**The decoder which was able to open the image source*/
|
||||
lv_img_decoder_t * decoder;
|
||||
|
||||
/**The image source. A file path like "S:my_img.png" or pointer to an `lv_img_dsc_t` variable*/
|
||||
const void * src;
|
||||
|
||||
/**Color to draw the image. USed when the image has alpha channel only*/
|
||||
lv_color_t color;
|
||||
|
||||
/**Frame of the image, using with animated images*/
|
||||
int32_t frame_id;
|
||||
|
||||
/**Type of the source: file or variable. Can be set in `open` function if required*/
|
||||
lv_img_src_t src_type;
|
||||
|
||||
/**Info about the opened image: color format, size, etc. MUST be set in `open` function*/
|
||||
lv_img_header_t header;
|
||||
|
||||
/** Pointer to a buffer where the image's data (pixels) are stored in a decoded, plain format.
|
||||
* MUST be set in `open` function*/
|
||||
const uint8_t * img_data;
|
||||
|
||||
/** How much time did it take to open the image. [ms]
|
||||
* If not set `lv_img_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;
|
||||
|
||||
/**Store any custom data here is required*/
|
||||
void * user_data;
|
||||
} lv_img_decoder_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the image decoder module
|
||||
*/
|
||||
void _lv_img_decoder_init(void);
|
||||
|
||||
/**
|
||||
* 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_add_drv()`)
|
||||
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
|
||||
* 3) Symbol: E.g. `LV_SYMBOL_OK`
|
||||
* @param header the image info will be stored here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image
|
||||
*/
|
||||
lv_res_t lv_img_decoder_get_info(const void * src, lv_img_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_img_decoder_dsc_t` variable.
|
||||
* @param src the image source. Can be
|
||||
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`)
|
||||
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
|
||||
* 3) Symbol: E.g. `LV_SYMBOL_OK`
|
||||
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
|
||||
* @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set.
|
||||
* LV_RES_INV: none of the registered image decoders were able to open the image.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id);
|
||||
|
||||
/**
|
||||
* Read a line from an opened image
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
* @param x start X coordinate (from left)
|
||||
* @param y start Y coordinate (from top)
|
||||
* @param len number of pixels to read
|
||||
* @param buf store the data here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: an error occurred
|
||||
*/
|
||||
lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len,
|
||||
uint8_t * buf);
|
||||
|
||||
/**
|
||||
* Close a decoding session
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
*/
|
||||
void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Create a new image decoder
|
||||
* @return pointer to the new image decoder
|
||||
*/
|
||||
lv_img_decoder_t * lv_img_decoder_create(void);
|
||||
|
||||
/**
|
||||
* Delete an image decoder
|
||||
* @param decoder pointer to an image decoder
|
||||
*/
|
||||
void lv_img_decoder_delete(lv_img_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_img_header_t` struct)
|
||||
*/
|
||||
void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_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_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_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_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_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_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb);
|
||||
|
||||
/**
|
||||
* Get info about a built-in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol
|
||||
* @param header store the image data here
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
|
||||
|
||||
/**
|
||||
* Open a built in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it.
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* 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 x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
|
||||
lv_coord_t y, lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**
|
||||
* Close the pending decoding. Free resources etc.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
*/
|
||||
void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_DECODER_H*/
|
||||
7
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_draw_nxp_pxp.mk
Normal file
7
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_draw_nxp_pxp.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
CSRCS += lv_gpu_nxp_pxp.c
|
||||
CSRCS += lv_gpu_nxp_pxp_osa.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_pxp
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_pxp
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_pxp"
|
||||
446
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c
Normal file
446
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_pxp.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
|
||||
#include "../misc/lv_mem.h"
|
||||
#include "../misc/lv_log.h"
|
||||
|
||||
#include "fsl_pxp.h"
|
||||
#include "fsl_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_COLOR_16_SWAP
|
||||
#error Color swap not implemented. Disable LV_COLOR_16_SWAP feature.
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
|
||||
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
|
||||
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
|
||||
#else
|
||||
#error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16.
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_gpu_nxp_pxp_run(void);
|
||||
static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src,
|
||||
lv_coord_t src_width,
|
||||
lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static bool colorKeyEnabled = false;
|
||||
static uint32_t colorKey = 0x0;
|
||||
|
||||
static bool recolorEnabled = false;
|
||||
static lv_color_t recolor = {.full = 0x0};
|
||||
static lv_opa_t recolorOpa = 0x0;
|
||||
|
||||
static lv_nxp_pxp_cfg_t pxp_cfg;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Reset and initialize PXP device. This function should be called as a part
|
||||
* of display init sequence.
|
||||
*
|
||||
* @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information.
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg)
|
||||
{
|
||||
if(!cfg || !cfg->pxp_interrupt_deinit || !cfg->pxp_interrupt_init || !cfg->pxp_run) {
|
||||
LV_LOG_ERROR("PXP configuration error. Check callback pointers.");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
PXP_Init(PXP);
|
||||
PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_EnableInterrupts(PXP, kPXP_CompleteInterruptEnable);
|
||||
|
||||
pxp_cfg = *cfg;
|
||||
if(pxp_cfg.pxp_interrupt_init() != LV_RES_OK) {
|
||||
PXP_Deinit(PXP);
|
||||
LV_LOG_ERROR("PXP interrupt init error. Check pxp_interrupt_init callback.");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
colorKey = lv_color_to32(LV_COLOR_CHROMA_KEY);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable PXP device. Should be called during display deinit sequence.
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_deinit(void)
|
||||
{
|
||||
pxp_cfg.pxp_interrupt_deinit();
|
||||
PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable);
|
||||
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill area, with optional opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_width width (stride) of destination buffer in pixels
|
||||
* @param[in] fill_area area to fill
|
||||
* @param[in] color color
|
||||
* @param[in] opa transparency of the color
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color,
|
||||
lv_opa_t opa)
|
||||
{
|
||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||
|
||||
/*OUT buffer configure*/
|
||||
pxp_output_buffer_config_t outputConfig = {
|
||||
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_width * fill_area->y1 + fill_area->x1),
|
||||
.buffer1Addr = (uint32_t)NULL,
|
||||
.pitchBytes = dest_width * sizeof(lv_color_t),
|
||||
.width = fill_area->x2 - fill_area->x1 + 1,
|
||||
.height = fill_area->y2 - fill_area->y1 + 1,
|
||||
};
|
||||
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
|
||||
|
||||
if(opa > LV_OPA_MAX) {
|
||||
/*Simple color fill without opacity - AS disabled, PS as color generator*/
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable AS.*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable PS.*/
|
||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
|
||||
}
|
||||
else {
|
||||
/*Fill with opacity - AS used as source (same as OUT), PS used as color generator, blended together*/
|
||||
pxp_as_buffer_config_t asBufferConfig;
|
||||
pxp_porter_duff_config_t pdConfig;
|
||||
|
||||
/*Set AS to OUT*/
|
||||
asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
|
||||
asBufferConfig.bufferAddr = (uint32_t)outputConfig.buffer0Addr;
|
||||
asBufferConfig.pitchBytes = outputConfig.pitchBytes;
|
||||
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, fill_area->x2 - fill_area->x1 + 1,
|
||||
fill_area->y2 - fill_area->y1 + 1);
|
||||
|
||||
/*Disable PS, use as color generator*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
|
||||
|
||||
/*Configure Porter-Duff blending - For RGB 565 only!*/
|
||||
pdConfig.enable = 1;
|
||||
pdConfig.dstColorMode = kPXP_PorterDuffColorStraight;
|
||||
pdConfig.srcColorMode = kPXP_PorterDuffColorStraight;
|
||||
pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
|
||||
pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
|
||||
pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight;
|
||||
pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight;
|
||||
pdConfig.srcGlobalAlpha = opa;
|
||||
pdConfig.dstGlobalAlpha = 255 - opa;
|
||||
pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
|
||||
pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
|
||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||
}
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects.
|
||||
*
|
||||
* By default, image is copied directly, with optional opacity configured by \p opa.
|
||||
* Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function.
|
||||
* Recoloring can be enabled by calling lv_gpu_nxp_pxp_enable_recolor() before calling this function.
|
||||
* Note that color keying and recoloring at the same time is not supported and black rectangle is rendered.
|
||||
*
|
||||
* @param[in/out] dest destination buffer
|
||||
* @param[in] dest_width width (stride) of destination buffer in pixels
|
||||
* @param[in] src source buffer
|
||||
* @param[in] src_with width (stride) of source buffer in pixels
|
||||
* @param[in] copy_w width of area to be copied from src to dest
|
||||
* @param[in] copy_h height of area to be copied from src to dest
|
||||
* @param[in] opa opacity of the result
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width,
|
||||
lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa)
|
||||
{
|
||||
|
||||
if(recolorEnabled) { /*switch to recolor version of blit*/
|
||||
lv_gpu_nxp_pxp_blit_recolor(dest, dest_width, src, src_width, copy_width, copy_height, opa, recolor, recolorOpa);
|
||||
return;
|
||||
};
|
||||
|
||||
PXP_Init(PXP);
|
||||
PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
||||
|
||||
pxp_output_buffer_config_t outputBufferConfig;
|
||||
pxp_as_buffer_config_t asBufferConfig;
|
||||
pxp_as_blend_config_t asBlendConfig;
|
||||
|
||||
asBlendConfig.alpha = opa;
|
||||
asBlendConfig.invertAlpha = false;
|
||||
asBlendConfig.alphaMode = kPXP_AlphaRop;
|
||||
asBlendConfig.ropMode = kPXP_RopMergeAs;
|
||||
|
||||
if(opa >= LV_OPA_MAX && !colorKeyEnabled) {
|
||||
/*Simple blit, no effect - Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
}
|
||||
else {
|
||||
/*Alpha blending or color keying enabled - PS must be enabled to fetch background pixels
|
||||
PS and OUT buffers are the same, blend will be done in-place*/
|
||||
pxp_ps_buffer_config_t psBufferConfig = {
|
||||
.pixelFormat = PXP_PS_PIXEL_FORMAT,
|
||||
.swapByte = false,
|
||||
.bufferAddr = (uint32_t)dest,
|
||||
.bufferAddrU = 0U,
|
||||
.bufferAddrV = 0U,
|
||||
.pitchBytes = dest_width * sizeof(lv_color_t)
|
||||
};
|
||||
asBlendConfig.alphaMode = kPXP_AlphaOverride;
|
||||
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1, copy_height - 1);
|
||||
}
|
||||
|
||||
/*AS buffer - source image*/
|
||||
asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
|
||||
asBufferConfig.bufferAddr = (uint32_t)src;
|
||||
asBufferConfig.pitchBytes = src_width * sizeof(lv_color_t);
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U);
|
||||
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
||||
|
||||
if(colorKeyEnabled) {
|
||||
PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKey, colorKey);
|
||||
}
|
||||
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKeyEnabled);
|
||||
|
||||
/*Output buffer.*/
|
||||
outputBufferConfig.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT;
|
||||
outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
|
||||
outputBufferConfig.buffer0Addr = (uint32_t)dest;
|
||||
outputBufferConfig.buffer1Addr = (uint32_t)0U;
|
||||
outputBufferConfig.pitchBytes = dest_width * sizeof(lv_color_t);
|
||||
outputBufferConfig.width = copy_width;
|
||||
outputBufferConfig.height = copy_height;
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /* Start PXP task */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
* Color key is defined by symbol in lv_conf.h
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_enable_color_key(void)
|
||||
{
|
||||
colorKeyEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_disable_color_key(void)
|
||||
{
|
||||
colorKeyEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
* @param[in] color recolor value
|
||||
* @param[in] opa effect opacity
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
recolorEnabled = true;
|
||||
recolor = color;
|
||||
recolorOpa = opa;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_disable_recolor(void)
|
||||
{
|
||||
recolorEnabled = false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Start PXP job and wait for results
|
||||
*
|
||||
* Function used internally to start PXP task according current device
|
||||
* configuration.
|
||||
*/
|
||||
static void lv_gpu_nxp_pxp_run(void)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
if(disp && disp->driver->clean_dcache_cb) { /* Clean & invalidate cache */
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
pxp_cfg.pxp_run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with recoloring.
|
||||
*
|
||||
* Note that color keying and recoloring at the same time is not supported and black rectangle is rendered.
|
||||
*
|
||||
* @param[in/out] dest destination buffer
|
||||
* @param[in] dest_width width (stride) of destination buffer in pixels
|
||||
* @param[in] src source buffer
|
||||
* @param[in] src_with width (stride) of source buffer in pixels
|
||||
* @param[in] copy_w width of area to be copied from src to dest
|
||||
* @param[in] copy_h height of area to be copied from src to dest
|
||||
* @param[in] opa opacity of the result
|
||||
* @param[in] recolor recolor value
|
||||
* @param[in] recolorOpa effect opacity
|
||||
*/
|
||||
static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src,
|
||||
lv_coord_t src_width,
|
||||
lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa)
|
||||
{
|
||||
pxp_output_buffer_config_t outputBufferConfig;
|
||||
pxp_as_buffer_config_t asBufferConfig;
|
||||
|
||||
if(colorKeyEnabled) {
|
||||
/*should never get here, recolor & color keying not supported. Draw black box instead.*/
|
||||
const lv_area_t fill_area = {.x1 = 0, .y1 = 0, .x2 = copy_width - 1, .y2 = copy_height - 1};
|
||||
lv_gpu_nxp_pxp_fill(dest, dest_width, &fill_area, lv_color_black(), LV_OPA_MAX);
|
||||
LV_LOG_WARN("Recoloring and color keying is not supported. Black rectangle rendered.");
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
/*Recoloring without color keying*/
|
||||
if(opa > LV_OPA_MAX) {
|
||||
/*Recolor with full opacity - AS source image, PS color generator, OUT destination*/
|
||||
PXP_Init(PXP);
|
||||
PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
||||
|
||||
/*AS buffer - source image*/
|
||||
asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
|
||||
asBufferConfig.bufferAddr = (uint32_t)src;
|
||||
asBufferConfig.pitchBytes = src_width * sizeof(lv_color_t);
|
||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U);
|
||||
|
||||
/*Disable PS buffer, use as color generator*/
|
||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(recolor));
|
||||
|
||||
/*Output buffer*/
|
||||
outputBufferConfig.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT;
|
||||
outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
|
||||
outputBufferConfig.buffer0Addr = (uint32_t)dest;
|
||||
outputBufferConfig.buffer1Addr = (uint32_t)0U;
|
||||
outputBufferConfig.pitchBytes = dest_width * sizeof(lv_color_t);
|
||||
outputBufferConfig.width = copy_width;
|
||||
outputBufferConfig.height = copy_height;
|
||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||
|
||||
pxp_porter_duff_config_t pdConfig;
|
||||
|
||||
/*Configure Porter-Duff blending - For RGB 565 only!*/
|
||||
pdConfig.enable = 1;
|
||||
pdConfig.dstColorMode = kPXP_PorterDuffColorStraight;
|
||||
pdConfig.srcColorMode = kPXP_PorterDuffColorStraight;
|
||||
pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
|
||||
pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
|
||||
pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight;
|
||||
pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight;
|
||||
pdConfig.srcGlobalAlpha = recolorOpa;
|
||||
pdConfig.dstGlobalAlpha = 255 - recolorOpa;
|
||||
pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
|
||||
pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
|
||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||
|
||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
||||
|
||||
}
|
||||
else {
|
||||
/*Recolor with transparency*/
|
||||
|
||||
/*Step 1: Recolor with full opacity to temporary buffer*/
|
||||
lv_color_t * tmpBuf = (lv_color_t *)lv_mem_buf_get(copy_width * copy_height * sizeof(lv_color_t));
|
||||
lv_gpu_nxp_pxp_blit_recolor(tmpBuf, copy_width, src, src_width, copy_width, copy_height, LV_OPA_COVER, recolor,
|
||||
recolorOpa);
|
||||
|
||||
/*Step 2: BLIT temporary results with required opacity to output*/
|
||||
lv_gpu_nxp_pxp_disable_recolor(); /*make sure to take BLIT path, not the recolor*/
|
||||
lv_gpu_nxp_pxp_blit(dest, dest_width, tmpBuf, copy_width, copy_width, copy_height, opa);
|
||||
lv_gpu_nxp_pxp_enable_recolor(recolor, recolorOpa); /*restore state*/
|
||||
|
||||
/*Step 3: Clean-up memory*/
|
||||
lv_mem_buf_release(tmpBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LV_USE_GPU_NXP_PXP */
|
||||
193
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h
Normal file
193
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_
|
||||
#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/** PXP module instance to use*/
|
||||
#define LV_GPU_NXP_PXP_ID PXP
|
||||
|
||||
/** PXP interrupt line I*/
|
||||
#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/
|
||||
#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/
|
||||
#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 16
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT
|
||||
/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */
|
||||
#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/
|
||||
#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 64
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) to be filled by PXP with transparency*/
|
||||
#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/**
|
||||
* NXP PXP device configuration - call-backs used for
|
||||
* interrupt init/wait/deinit.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Callback for PXP interrupt initialization*/
|
||||
lv_res_t (*pxp_interrupt_init)(void);
|
||||
|
||||
/** Callback for PXP interrupt de-initialization*/
|
||||
void (*pxp_interrupt_deinit)(void);
|
||||
|
||||
/** Callback that should start PXP and wait for operation complete*/
|
||||
void (*pxp_run)(void);
|
||||
} lv_nxp_pxp_cfg_t;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Reset and initialize PXP device. This function should be called as a part
|
||||
* of display init sequence.
|
||||
*
|
||||
* @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information.
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg);
|
||||
|
||||
/**
|
||||
* Disable PXP device. Should be called during display deinit sequence.
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_deinit(void);
|
||||
|
||||
/**
|
||||
* Fill area, with optional opacity.
|
||||
*
|
||||
* @param[in/out] dest_buf destination buffer
|
||||
* @param[in] dest_width width (stride) of destination buffer in pixels
|
||||
* @param[in] fill_area area to fill
|
||||
* @param[in] color color
|
||||
* @param[in] opa transparency of the color
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color,
|
||||
lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects.
|
||||
*
|
||||
* By default, image is copied directly, with optional opacity configured by \p opa.
|
||||
* Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function.
|
||||
* Recoloring can be enabled by calling lv_gpu_nxp_pxp_enable_recolor() before calling this function.
|
||||
* Note that color keying and recoloring at the same time is not supported and black rectangle is rendered.
|
||||
*
|
||||
* @param[in/out] dest destination buffer
|
||||
* @param[in] dest_width width (stride) of destination buffer in pixels
|
||||
* @param[in] src source buffer
|
||||
* @param[in] src_with width (stride) of source buffer in pixels
|
||||
* @param[in] copy_w width of area to be copied from src to dest
|
||||
* @param[in] copy_h height of area to be copied from src to dest
|
||||
* @param[in] opa opacity of the result
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width,
|
||||
lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
* Color key is defined by LV_COLOR_TRANSP symbol in lv_conf.h
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_enable_color_key(void);
|
||||
|
||||
/**
|
||||
* @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_disable_color_key(void);
|
||||
|
||||
/**
|
||||
* @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*
|
||||
* @param[in] color recolor value
|
||||
* @param[in] opa effect opacity
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
|
||||
*/
|
||||
void lv_gpu_nxp_pxp_disable_recolor(void);
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_*/
|
||||
166
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c
Normal file
166
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp_osa.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_pxp_osa.h"
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "../misc/lv_log.h"
|
||||
|
||||
|
||||
#include "lv_gpu_nxp_pxp.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void);
|
||||
static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
|
||||
static void _lv_gpu_nxp_pxp_run(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
static SemaphoreHandle_t s_pxpIdle;
|
||||
#else
|
||||
static volatile bool s_pxpIdle;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP device interrupt handler. Used to check PXP task completion status.
|
||||
*/
|
||||
void PXP_IRQHandler(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
BaseType_t taskAwake = pdFALSE;
|
||||
#endif
|
||||
|
||||
if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
|
||||
PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake);
|
||||
portYIELD_FROM_ISR(taskAwake);
|
||||
#else
|
||||
s_pxpIdle = true;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP interrupt initialization.
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
s_pxpIdle = xSemaphoreCreateBinary();
|
||||
if(s_pxpIdle == NULL) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||
#else
|
||||
s_pxpIdle = true;
|
||||
#endif
|
||||
|
||||
NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* PXP interrupt de-initialization.
|
||||
*/
|
||||
static void _lv_gpu_nxp_pxp_interrupt_deinit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
vSemaphoreDelete(s_pxpIdle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to start PXP job. This function must wait for task complete.
|
||||
*/
|
||||
static void _lv_gpu_nxp_pxp_run(void)
|
||||
{
|
||||
#if !defined(SDK_OS_FREE_RTOS)
|
||||
s_pxpIdle = false;
|
||||
#endif
|
||||
|
||||
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
PXP_Start(LV_GPU_NXP_PXP_ID);
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
if(xSemaphoreTake(s_pxpIdle, portMAX_DELAY) != pdTRUE) {
|
||||
LV_LOG_ERROR("xSemaphoreTake error. Task halted.");
|
||||
for(; ;) ;
|
||||
}
|
||||
#else
|
||||
while(s_pxpIdle == false) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_nxp_pxp_cfg_t pxp_default_cfg = {
|
||||
.pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
|
||||
.pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
|
||||
.pxp_run = _lv_gpu_nxp_pxp_run
|
||||
};
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/
|
||||
47
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h
Normal file
47
LVGL.Simulator/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_pxp_osa.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_
|
||||
#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
extern lv_nxp_pxp_cfg_t pxp_default_cfg;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_*/
|
||||
@@ -0,0 +1,6 @@
|
||||
CSRCS += lv_gpu_nxp_vglite.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_vglite
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_vglite
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp_vglite"
|
||||
770
LVGL.Simulator/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c
Normal file
770
LVGL.Simulator/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c
Normal file
@@ -0,0 +1,770 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_vglite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gpu_nxp_vglite.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "fsl_cache.h"
|
||||
#include "vg_lite.h"
|
||||
#include "fsl_debug_console.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_COLOR_DEPTH==16
|
||||
#define VGLITE_PX_FMT VG_LITE_RGB565
|
||||
#else
|
||||
#error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16.
|
||||
#endif
|
||||
|
||||
/* Enable BLIT quality degradation workaround for RT595 */
|
||||
#define RT595_BLIT_WRKRND_ENABLED 1
|
||||
|
||||
/* If LV_HOR_RES_MAX/LV_VER_RES_MAX is higher than this value, workaround will be enabled */
|
||||
#define RT595_BLIT_WRKRND_THR 352
|
||||
|
||||
/* Print detailed info to SDK console (NOT to LVGL log system) */
|
||||
#define BLIT_DBG_VERBOSE 0
|
||||
|
||||
/* Draw rectangles around BLIT tiles */
|
||||
#define BLIT_DBG_AREAS 0
|
||||
|
||||
/* Redirect PRINT to SDK PRINTF */
|
||||
#define PRINT PRINTF
|
||||
|
||||
/* Verbose debug print */
|
||||
#if BLIT_DBG_VERBOSE
|
||||
#define PRINT_BLT PRINTF
|
||||
#else
|
||||
#define PRINT_BLT(...)
|
||||
#endif
|
||||
|
||||
/* Internal compound symbol */
|
||||
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
|
||||
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
|
||||
((LV_HOR_RES_MAX > RT595_BLIT_WRKRND_THR) || (LV_VER_RES_MAX > RT595_BLIT_WRKRND_THR)) && \
|
||||
RT595_BLIT_WRKRND_ENABLED
|
||||
#define _BLIT_SPLIT_ENABLED 1
|
||||
#else
|
||||
#define _BLIT_SPLIT_ENABLED 0
|
||||
#endif
|
||||
|
||||
/* BLIT split threshold - BLITs with width or height higher than this value will be done
|
||||
* in multiple steps. Value must be 16-aligned. Don't change.
|
||||
* */
|
||||
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride,
|
||||
const lv_color_t * ptr, bool source);
|
||||
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
#if _BLIT_SPLIT_ENABLED
|
||||
static void _align_x(lv_area_t * area, lv_color_t ** buf);
|
||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx);
|
||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
#if BLIT_DBG_AREAS
|
||||
static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
lv_area_t * fill_area, lv_color_t color);
|
||||
#endif
|
||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define CHECK(cond, txt) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
PRINT("%s. STOP!\n", txt); \
|
||||
for ( ; ; ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/***
|
||||
* Fills rectangular area in buffer.
|
||||
* @param[in] dest_buf Destination buffer pointer (must be aligned on 32 bytes)
|
||||
* @param[in] dest_width Destination buffer width in pixels (must be aligned on 16 px)
|
||||
* @param[in] dest_height Destination buffer height in pixels
|
||||
* @param[in] fill_area Area to be filled
|
||||
* @param[in] color Fill color
|
||||
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
vg_lite_buffer_t rt;
|
||||
vg_lite_rectangle_t rect;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
if(_init_vg_buf(&rt, (uint32_t) dest_width, (uint32_t) dest_height, (uint32_t) dest_width * sizeof(lv_color_t),
|
||||
(const lv_color_t *) dest_buf, false) != LV_RES_OK) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("init_vg_buf reported error. Fill failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(opa >= (lv_opa_t) LV_OPA_MAX) { /*Opaque fill*/
|
||||
rect.x = fill_area->x1;
|
||||
rect.y = fill_area->y1;
|
||||
rect.width = (int32_t) fill_area->x2 - (int32_t) fill_area->x1 + 1;
|
||||
rect.height = (int32_t) fill_area->y2 - (int32_t) fill_area->y1 + 1;
|
||||
|
||||
if(disp != NULL && disp->driver->clean_dcache_cb != NULL) { /*Clean & invalidate cache*/
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
err = vg_lite_clear(&rt, &rect, col32.full);
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_clear reported error. Fill failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
err = vg_lite_finish();
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_finish reported error. Fill failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
else { /*fill with transparency*/
|
||||
|
||||
vg_lite_path_t path;
|
||||
lv_color32_t colMix;
|
||||
int16_t path_data[] = { /*VG rectangular path*/
|
||||
VLC_OP_MOVE, fill_area->x1, fill_area->y1,
|
||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1,
|
||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1,
|
||||
VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1,
|
||||
VLC_OP_LINE, fill_area->x1, fill_area->y1,
|
||||
VLC_OP_END
|
||||
};
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data,
|
||||
(vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, ((vg_lite_float_t) fill_area->x2) + 1.0f,
|
||||
((vg_lite_float_t) fill_area->y2) + 1.0f);
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_init_path() failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
colMix.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); /*Pre-multiply color*/
|
||||
colMix.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
|
||||
colMix.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
|
||||
colMix.ch.alpha = opa;
|
||||
|
||||
if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*Draw rectangle*/
|
||||
err = vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full);
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_draw() failed.");
|
||||
#endif
|
||||
vg_lite_clear_path(&path);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
err = vg_lite_finish();
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_finish() failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_clear_path() failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
if(err == VG_LITE_SUCCESS) {
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("VG Lite Fill failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* BLock Image Transfer.
|
||||
* @param[in] blit Description of the transfer
|
||||
* @retval LV_RES_OK Transfer complete
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
#if _BLIT_SPLIT_ENABLED
|
||||
|
||||
lv_res_t rv = LV_RES_INV;
|
||||
|
||||
if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) {
|
||||
PRINT_BLT("Blit check failed\n");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
PRINT_BLT("BLIT from: "
|
||||
"Area: %03d,%03d - %03d,%03d "
|
||||
"Addr: %d\n\n",
|
||||
blit->src_area.x1, blit->src_area.y1,
|
||||
blit->src_area.x2, blit->src_area.y2,
|
||||
(uintptr_t) blit->src);
|
||||
|
||||
PRINT_BLT("BLIT to: "
|
||||
"Area: %03d,%03d - %03d,%03d "
|
||||
"Addr: %d\n\n",
|
||||
blit->dst_area.x1, blit->dst_area.y1,
|
||||
blit->dst_area.x2, blit->dst_area.y2,
|
||||
(uintptr_t) blit->src);
|
||||
|
||||
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
|
||||
_align_x(&blit->src_area, (lv_color_t **)&blit->src);
|
||||
_align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t));
|
||||
_align_x(&blit->dst_area, (lv_color_t **)&blit->dst);
|
||||
_align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t));
|
||||
|
||||
/* Stage 2: If we're in limit, do a single BLIT */
|
||||
if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
|
||||
(blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
|
||||
PRINT_BLT("Simple blit!\n");
|
||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
||||
};
|
||||
|
||||
/* Stage 3: Split the BLIT into multiple tiles */
|
||||
PRINT_BLT("Split blit!\n");
|
||||
|
||||
PRINT_BLT("Blit "
|
||||
"([%03d,%03d], [%03d,%03d]) -> "
|
||||
"([%03d,%03d], [%03d,%03d]) | "
|
||||
"([%03dx%03d] -> [%03dx%03d]) | "
|
||||
"A:(%d -> %d)\n",
|
||||
blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2,
|
||||
blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2,
|
||||
lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area),
|
||||
lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area),
|
||||
(uintptr_t) blit->src, (uintptr_t) blit->dst);
|
||||
|
||||
|
||||
uint32_t totalWidth = lv_area_get_width(&blit->src_area);
|
||||
uint32_t totalHeight = lv_area_get_height(&blit->src_area);
|
||||
|
||||
lv_gpu_nxp_vglite_blit_info_t tileBlit;
|
||||
|
||||
/* Number of tiles needed */
|
||||
int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
|
||||
/* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as
|
||||
* the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be
|
||||
* different */
|
||||
int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0;
|
||||
int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0;
|
||||
|
||||
PRINT_BLT("\n");
|
||||
PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX);
|
||||
|
||||
tileBlit = *blit;
|
||||
|
||||
for(int tileY = 0; tileY < totalTilesY; tileY++) {
|
||||
|
||||
tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */
|
||||
tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
|
||||
}
|
||||
tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof(
|
||||
lv_color_t); /* stride in px! */
|
||||
|
||||
tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */
|
||||
tileBlit.dst_area.y2 = tileBlit.src_area.y2;
|
||||
|
||||
tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof(
|
||||
lv_color_t); /* stride in px! */
|
||||
|
||||
for(int tileX = 0; tileX < totalTilesX; tileX++) {
|
||||
|
||||
if(tileX == 0) {
|
||||
/* 1st tile is special - there may be a gap between buffer start pointer
|
||||
* and area.x1 value, as the pointer has to be aligned.
|
||||
* tileBlit.src pointer - keep init value from Y-loop.
|
||||
* Also, 1st tile start is not shifted! shift is applied from 2nd tile */
|
||||
tileBlit.src_area.x1 = blit->src_area.x1;
|
||||
tileBlit.dst_area.x1 = blit->dst_area.x1;
|
||||
}
|
||||
else {
|
||||
/* subsequent tiles always starts from 0, but shifted*/
|
||||
tileBlit.src_area.x1 = 0 + shiftSrcX;
|
||||
tileBlit.dst_area.x1 = 0 + shiftDstX;
|
||||
/* and advance start pointer + 1 tile size */
|
||||
tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||
}
|
||||
|
||||
/* Clip tile end coordinates */
|
||||
tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
}
|
||||
|
||||
tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||
tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||
}
|
||||
|
||||
if(tileX < (totalTilesX - 1)) {
|
||||
/* And adjust end coords if shifted, but not for last tile! */
|
||||
tileBlit.src_area.x2 += shiftSrcX;
|
||||
tileBlit.dst_area.x2 += shiftDstX;
|
||||
}
|
||||
|
||||
rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit);
|
||||
|
||||
#if BLIT_DBG_AREAS
|
||||
_draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area, LV_COLOR_RED);
|
||||
_draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area,
|
||||
LV_COLOR_GREEN);
|
||||
#endif
|
||||
|
||||
PRINT_BLT("Tile [%d, %d]: "
|
||||
"([%d,%d], [%d,%d]) -> "
|
||||
"([%d,%d], [%d,%d]) | "
|
||||
"([%dx%d] -> [%dx%d]) | "
|
||||
"A:(0x%8X -> 0x%8X) %s\n",
|
||||
tileX, tileY,
|
||||
tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2,
|
||||
tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2,
|
||||
lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area),
|
||||
lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area),
|
||||
(uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst,
|
||||
rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!");
|
||||
|
||||
if(rv != LV_RES_OK) { /* if anything goes wrong... */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("Split BLIT failed. Trying SW BLIT instead.");
|
||||
#endif
|
||||
_sw_blit(&tileBlit);
|
||||
rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */
|
||||
}
|
||||
|
||||
}
|
||||
PRINT_BLT(" \n");
|
||||
}
|
||||
|
||||
return rv; /* should never fail */
|
||||
|
||||
#else /* non RT595 */
|
||||
/* Just pass down */
|
||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/***
|
||||
* BLock Image Transfer - single direct BLIT.
|
||||
* @param[in] blit Description of the transfer
|
||||
* @retval LV_RES_OK Transfer complete
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
vg_lite_buffer_t src_vgbuf, dst_vgbuf;
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
uint32_t rect[4];
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
if(blit == NULL) {
|
||||
/*Wrong parameter*/
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(blit->opa < (lv_opa_t) LV_OPA_MIN) {
|
||||
return LV_RES_OK; /*Nothing to BLIT*/
|
||||
}
|
||||
|
||||
/*Wrap src/dst buffer into VG-Lite buffer*/
|
||||
if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride,
|
||||
blit->src, true) != LV_RES_OK) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("init_vg_buf reported error. BLIT failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride,
|
||||
blit->dst, false) != LV_RES_OK) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("init_vg_buf reported error. BLIT failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
rect[0] = (uint32_t) blit->src_area.x1; /* start x */
|
||||
rect[1] = (uint32_t) blit->src_area.y1; /* start y */
|
||||
rect[2] = (uint32_t) blit->src_area.x2 - (uint32_t) blit->src_area.x1 + 1U; /* width */
|
||||
rect[3] = (uint32_t) blit->src_area.y2 - (uint32_t) blit->src_area.y1 + 1U; /* height */
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix);
|
||||
|
||||
if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
uint32_t color;
|
||||
vg_lite_blend_t blend;
|
||||
if(blit->opa >= (uint8_t) LV_OPA_MAX) {
|
||||
color = 0x0;
|
||||
blend = VG_LITE_BLEND_NONE;
|
||||
}
|
||||
else {
|
||||
uint32_t opa = (uint32_t) blit->opa;
|
||||
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
|
||||
blend = VG_LITE_BLEND_SRC_OVER;
|
||||
src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
}
|
||||
|
||||
err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT);
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_blit_rect() failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
err = vg_lite_finish();
|
||||
if(err != VG_LITE_SUCCESS) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_finish() failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(err == VG_LITE_SUCCESS) {
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("vg_lite_blit_rect or vg_lite_finish reported error. BLIT failed.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Fills vg_lite_buffer_t structure according given parameters.
|
||||
* @param[out] dst Buffer structure to be filled
|
||||
* @param[in] width Width of buffer in pixels
|
||||
* @param[in] height Height of buffer in pixels
|
||||
* @param[in] stride Stride of the buffer in bytes
|
||||
* @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements)
|
||||
*/
|
||||
static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride,
|
||||
const lv_color_t * ptr, bool source)
|
||||
{
|
||||
if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0U) { /*Test for alignment*/
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("ptr (0x%X) not aligned to %d.", (size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(source &&
|
||||
(stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
dst->format = VGLITE_PX_FMT;
|
||||
dst->tiled = VG_LITE_LINEAR;
|
||||
dst->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
|
||||
dst->transparency_mode = VG_LITE_IMAGE_OPAQUE;
|
||||
|
||||
dst->width = (int32_t) width;
|
||||
dst->height = (int32_t) height;
|
||||
dst->stride = (int32_t) stride;
|
||||
|
||||
void * r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv));
|
||||
if(r_ptr == NULL) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
dst->memory = (void *)ptr;
|
||||
dst->address = (uint32_t) dst->memory;
|
||||
dst->handle = NULL;
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#if _BLIT_SPLIT_ENABLED
|
||||
|
||||
/**
|
||||
* Software BLIT as a fall-back scenario
|
||||
* @param[in] blit BLIT configuration
|
||||
*/
|
||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&blit->src_area);
|
||||
lv_coord_t h = lv_area_get_height(&blit->src_area);
|
||||
|
||||
uint32_t srcStridePx = blit->src_stride / sizeof(lv_color_t);
|
||||
uint32_t dstStridePx = blit->dst_stride / sizeof(lv_color_t);
|
||||
|
||||
lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1;
|
||||
lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1;
|
||||
|
||||
if(blit->opa >= LV_OPA_MAX) {
|
||||
/* simple copy */
|
||||
for(y = 0; y < h; y++) {
|
||||
_lv_memcpy(dst, src, w * sizeof(lv_color_t));
|
||||
src += srcStridePx;
|
||||
dst += dstStridePx;
|
||||
}
|
||||
}
|
||||
else if(blit->opa >= LV_OPA_MIN) {
|
||||
/* alpha blending */
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
dst[x] = lv_color_mix(src[x], dst[x], blit->opa);
|
||||
}
|
||||
src += srcStridePx;
|
||||
dst += dstStridePx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify BLIT structure - widths, stride, pointer alignment
|
||||
* @param[in] blit
|
||||
* @return
|
||||
*/
|
||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
||||
{
|
||||
|
||||
if(lv_area_get_width(&blit->src_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("source area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area),
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(lv_area_get_width(&blit->dst_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("destination area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area),
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /* Test for pointer alignment */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("source buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
|
||||
|
||||
if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) !=
|
||||
0x0) { /* Test for stride alignment */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) !=
|
||||
0x0) { /* Test for stride alignment */
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride,
|
||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) ||
|
||||
(lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area))) {
|
||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
LV_LOG_ERROR("source and destination buffer areas are not equal.");
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/***
|
||||
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
|
||||
* @param[in,out] area Area to be updated
|
||||
* @param[in,out] buf Pointer to be updated
|
||||
*/
|
||||
static void _align_x(lv_area_t * area, lv_color_t ** buf)
|
||||
{
|
||||
|
||||
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH));
|
||||
CHECK(alignedAreaStartPx < 0, "Should never happen.");
|
||||
|
||||
area->x1 -= alignedAreaStartPx;
|
||||
area->x2 -= alignedAreaStartPx;
|
||||
*buf += alignedAreaStartPx;
|
||||
}
|
||||
|
||||
/***
|
||||
* Move buffer pointer to the area start and update variables, Y-axis only.
|
||||
* @param[in,out] area Area to be updated
|
||||
* @param[in,out] buf Pointer to be updated
|
||||
* @param[in] stridePx Buffer stride in pixels
|
||||
*/
|
||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
|
||||
{
|
||||
int LineToAlignMem;
|
||||
int alignedAreaStartPy;
|
||||
/* find how many lines of pixels will respect memory alignment requirement */
|
||||
if(stridePx % LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0) {
|
||||
alignedAreaStartPy = area->y1;
|
||||
}
|
||||
else {
|
||||
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||
CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0,
|
||||
"Complex case: need gcd function.");
|
||||
alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem);
|
||||
CHECK(alignedAreaStartPy < 0, "Should never happen.");
|
||||
}
|
||||
|
||||
area->y1 -= alignedAreaStartPy;
|
||||
area->y2 -= alignedAreaStartPy;
|
||||
*buf += alignedAreaStartPy * stridePx;
|
||||
}
|
||||
|
||||
#if BLIT_DBG_AREAS
|
||||
/***
|
||||
* Draws a simple rectangle, 1 px line width.
|
||||
* @param dest_buf Destination buffer
|
||||
* @param dest_width Destination buffer width (must be aligned on 16px)
|
||||
* @param dest_height Destination buffer height
|
||||
* @param fill_area Rectangle coordinates
|
||||
* @param color Rectangle color
|
||||
*/
|
||||
static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
lv_area_t * fill_area, lv_color_t color)
|
||||
{
|
||||
|
||||
lv_area_t a;
|
||||
|
||||
/* top line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y1;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
|
||||
/* bottom line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y2;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
/* left line */
|
||||
a.x1 = fill_area->x1;
|
||||
a.x2 = fill_area->x1;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
|
||||
/* right line */
|
||||
a.x1 = fill_area->x2;
|
||||
a.x2 = fill_area->x2;
|
||||
a.y1 = fill_area->y1;
|
||||
a.y2 = fill_area->y2;
|
||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
||||
}
|
||||
#endif /* BLIT_DBG_AREAS */
|
||||
|
||||
#endif /* _BLIT_SPLIT_ENABLED */
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
145
LVGL.Simulator/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h
Normal file
145
LVGL.Simulator/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* @file lv_gpu_nxp_vglite.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 NXP
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next paragraph)
|
||||
* shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_
|
||||
#define LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */
|
||||
#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1)
|
||||
|
||||
/** Stride in px required by VG-Lite HW. Don't change this. */
|
||||
#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/
|
||||
#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) to be filled by VG-Lite with transparency*/
|
||||
#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by VG-Lite*/
|
||||
#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT
|
||||
/** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */
|
||||
#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT
|
||||
/** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/
|
||||
#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 32
|
||||
#endif
|
||||
|
||||
#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
||||
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* BLock Image Transfer descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
const lv_color_t * src; /**< Source buffer pointer (must be aligned on 32 bytes)*/
|
||||
lv_area_t src_area; /**< Area to be copied from source*/
|
||||
lv_coord_t src_width; /**< Source buffer width*/
|
||||
lv_coord_t src_height; /**< Source buffer height*/
|
||||
uint32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/
|
||||
|
||||
const lv_color_t * dst; /**< Destination buffer pointer (must be aligned on 32 bytes)*/
|
||||
lv_area_t dst_area; /**< Target area in destination buffer (must be the same as src_area)*/
|
||||
lv_coord_t dst_width; /**< Destination buffer width*/
|
||||
lv_coord_t dst_height; /**< Destination buffer height*/
|
||||
uint32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/
|
||||
|
||||
lv_opa_t opa; /**< Opacity - alpha mix (0 = source not copied, 255 = 100% opaque)*/
|
||||
|
||||
} lv_gpu_nxp_vglite_blit_info_t;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/***
|
||||
* Fills rectangular area in buffer.
|
||||
* @param[in] dest_buf Destination buffer pointer (must be aligned on 32 bytes)
|
||||
* @param[in] dest_width Destination buffer width in pixels ((must be aligned on 16 px)
|
||||
* @param[in] dest_height Destination buffer height in pixels
|
||||
* @param[in] fill_area Area to be filled
|
||||
* @param[in] color Fill color
|
||||
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
|
||||
* @retval LV_RES_OK Fill completed
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
||||
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/***
|
||||
* BLock Image Transfer.
|
||||
* @param[in] blit Description of the transfer
|
||||
* @retval LV_RES_OK Transfer complete
|
||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||
*/
|
||||
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
||||
|
||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_*/
|
||||
28
LVGL.Simulator/lvgl/src/draw/sdl/README.md
Normal file
28
LVGL.Simulator/lvgl/src/draw/sdl/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# SDL_Renderer Based Drawing Functions
|
||||
|
||||
In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU,
|
||||
we should perform drawing operations on GPU if possible.
|
||||
|
||||
This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer,
|
||||
which takes advantages of hardware acceleration APIs like DirectX or OpenGL.
|
||||
|
||||
This implementation can be also considered as a reference implementation, for contributors wants to
|
||||
develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES.
|
||||
|
||||
## Caveats
|
||||
`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will
|
||||
have significant impact to drawing performances.
|
||||
|
||||
Performance of this implementation still has room to improve. Or we should use more powerful APIs
|
||||
such as OpenGL.
|
||||
|
||||
## Notices for files
|
||||
|
||||
### `lv_draw_sdl_stack_blur.c`
|
||||
|
||||
Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project.
|
||||
Apache License 2.0
|
||||
|
||||
### `lv_draw_sdl_lru.c`/`lv_draw_sdl_lru.h`
|
||||
|
||||
Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined.
|
||||
98
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.c
Normal file
98
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file lv_draw_sdl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src);
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2);
|
||||
|
||||
void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
||||
|
||||
void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points,
|
||||
uint16_t point_cnt);
|
||||
|
||||
void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
_lv_draw_sdl_utils_init();
|
||||
lv_memset_00(draw_ctx, sizeof(lv_draw_sdl_ctx_t));
|
||||
draw_ctx->draw_rect = lv_draw_sdl_draw_rect;
|
||||
draw_ctx->draw_img = lv_draw_sdl_img_core;
|
||||
draw_ctx->draw_letter = lv_draw_sdl_draw_letter;
|
||||
draw_ctx->draw_line = lv_draw_sdl_draw_line;
|
||||
draw_ctx->draw_arc = lv_draw_sdl_draw_arc;
|
||||
draw_ctx->draw_polygon = lv_draw_sdl_polygon;
|
||||
draw_ctx->draw_bg = lv_draw_sdl_draw_bg;
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
draw_ctx_sdl->renderer = (lv_draw_sdl_drv_param_t *) disp_drv->user_data;
|
||||
draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_memset_00(draw_ctx_sdl->internals, sizeof(lv_draw_sdl_context_internals_t));
|
||||
lv_draw_sdl_texture_cache_init(draw_ctx_sdl);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
lv_draw_sdl_texture_cache_deinit(draw_ctx_sdl);
|
||||
lv_mem_free(draw_ctx_sdl->internals);
|
||||
_lv_draw_sdl_utils_deinit();
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver)
|
||||
{
|
||||
SDL_Texture * texture = SDL_CreateTexture(renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, hor, ver);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
96
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.h
Normal file
96
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file lv_draw_sdl.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_H
|
||||
#define LV_DRAW_SDL_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../../core/lv_disp.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_ARGB8888
|
||||
#else
|
||||
#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_RGBA8888
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct lv_draw_sdl_context_internals_t;
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* Render for display driver
|
||||
*/
|
||||
SDL_Renderer * renderer;
|
||||
void * user_data;
|
||||
} lv_draw_sdl_drv_param_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_ctx_t base_draw;
|
||||
SDL_Renderer * renderer;
|
||||
struct lv_draw_sdl_context_internals_t * internals;
|
||||
} lv_draw_sdl_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**
|
||||
* @brief Free caches
|
||||
*
|
||||
*/
|
||||
void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_H*/
|
||||
18
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.mk
Normal file
18
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
CSRCS += lv_draw_sdl.c
|
||||
CSRCS += lv_draw_sdl_arc.c
|
||||
CSRCS += lv_draw_sdl_bg.c
|
||||
CSRCS += lv_draw_sdl_composite.c
|
||||
CSRCS += lv_draw_sdl_img.c
|
||||
CSRCS += lv_draw_sdl_label.c
|
||||
CSRCS += lv_draw_sdl_line.c
|
||||
CSRCS += lv_draw_sdl_mask.c
|
||||
CSRCS += lv_draw_sdl_polygon.c
|
||||
CSRCS += lv_draw_sdl_rect.c
|
||||
CSRCS += lv_draw_sdl_stack_blur.c
|
||||
CSRCS += lv_draw_sdl_texture_cache.c
|
||||
CSRCS += lv_draw_sdl_utils.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl"
|
||||
238
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_arc.c
Normal file
238
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_arc.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps);
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
lv_area_t area_out;
|
||||
area_out.x1 = center->x - radius;
|
||||
area_out.y1 = center->y - radius;
|
||||
area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/
|
||||
area_out.y2 = center->y + radius - 1;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_out, draw_ctx->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t area_in;
|
||||
lv_area_copy(&area_in, &area_out);
|
||||
area_in.x1 += dsc->width;
|
||||
area_in.y1 += dsc->width;
|
||||
area_in.x2 -= dsc->width;
|
||||
area_in.y2 -= dsc->width;
|
||||
|
||||
|
||||
while(start_angle >= 360) start_angle -= 360;
|
||||
while(end_angle >= 360) end_angle -= 360;
|
||||
|
||||
int16_t mask_ids[3] = {LV_MASK_ID_INV, LV_MASK_ID_INV, LV_MASK_ID_INV}, mask_ids_count = 1;
|
||||
int16_t cap_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV};
|
||||
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
|
||||
mask_ids[0] = lv_draw_mask_add(&mask_out_param, NULL);
|
||||
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
|
||||
lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
|
||||
mask_ids[1] = lv_draw_mask_add(&mask_in_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_angle_param_t mask_angle_param;
|
||||
if((start_angle - end_angle) % 360) {
|
||||
lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
|
||||
mask_ids[2] = lv_draw_mask_add(&mask_angle_param, NULL);
|
||||
mask_ids_count++;
|
||||
}
|
||||
|
||||
lv_draw_mask_radius_param_t cap_start_param, cap_end_param;
|
||||
if(mask_ids_count == 3 && dsc->rounded) {
|
||||
lv_area_t start_area, end_area;
|
||||
get_cap_area((int16_t) start_angle, dsc->width, radius, center, &start_area);
|
||||
get_cap_area((int16_t) end_angle, dsc->width, radius, center, &end_area);
|
||||
lv_draw_mask_radius_init(&cap_start_param, &start_area, dsc->width / 2, false);
|
||||
cap_ids[0] = lv_draw_mask_add(&cap_start_param, NULL);
|
||||
lv_draw_mask_radius_init(&cap_end_param, &end_area, dsc->width / 2, false);
|
||||
cap_ids[1] = lv_draw_mask_add(&cap_end_param, NULL);
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
|
||||
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL);
|
||||
|
||||
lv_draw_mask_remove_id(mask_ids[0]);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
|
||||
if(mask_ids_count > 1) {
|
||||
lv_draw_mask_remove_id(mask_ids[1]);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
}
|
||||
|
||||
if(mask_ids_count > 2) {
|
||||
lv_draw_mask_remove_id(mask_ids[2]);
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
}
|
||||
|
||||
if(cap_ids[0] != LV_MASK_ID_INV) {
|
||||
lv_draw_mask_remove_id(cap_ids[0]);
|
||||
lv_draw_mask_remove_id(cap_ids[1]);
|
||||
lv_draw_mask_free_param(&cap_start_param);
|
||||
lv_draw_mask_free_param(&cap_end_param);
|
||||
}
|
||||
|
||||
SDL_Rect srcrect = {0, 0, w, h}, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&dsc->color, &color);
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->opa);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count,
|
||||
const int16_t * caps)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
*pixel = line_buf[x];
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
if(caps) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, &caps[i], 1);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
/* Ignore */
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
uint16_t old_opa = line_buf[x] + *pixel;
|
||||
*pixel = LV_MIN(old_opa, 0xFF);
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center,
|
||||
lv_area_t * out)
|
||||
{
|
||||
const uint8_t ps = 8;
|
||||
const uint8_t pa = 127;
|
||||
|
||||
int32_t thick_half = thickness / 2;
|
||||
uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
|
||||
|
||||
int32_t cir_x;
|
||||
int32_t cir_y;
|
||||
|
||||
cir_x = ((radius - thick_half) * lv_trigo_sin((int16_t)(90 - angle))) >> (LV_TRIGO_SHIFT - ps);
|
||||
cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
|
||||
/*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
|
||||
if(cir_x > 0) {
|
||||
cir_x = (cir_x - pa) >> ps;
|
||||
out->x1 = cir_x - thick_half + thick_corr;
|
||||
out->x2 = cir_x + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_x = (cir_x + pa) >> ps;
|
||||
out->x1 = cir_x - thick_half;
|
||||
out->x2 = cir_x + thick_half - thick_corr;
|
||||
}
|
||||
|
||||
if(cir_y > 0) {
|
||||
cir_y = (cir_y - pa) >> ps;
|
||||
out->y1 = cir_y - thick_half + thick_corr;
|
||||
out->y2 = cir_y + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_y = (cir_y + pa) >> ps;
|
||||
out->y1 = cir_y - thick_half;
|
||||
out->y2 = cir_y + thick_half - thick_corr;
|
||||
}
|
||||
lv_area_move(out, center->x, center->y);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
106
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_bg.c
Normal file
106
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_bg.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_bg.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_area;
|
||||
bool has_content = _lv_area_intersect(&t_area, coords, clip);
|
||||
|
||||
/* Shadows and outlines will also draw in extended area */
|
||||
if(has_content) {
|
||||
if(dsc->bg_img_src) {
|
||||
draw_bg_img(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
else {
|
||||
draw_bg_color(ctx, coords, &t_area, dsc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_Color bg_color;
|
||||
lv_color_to_sdl_color(&dsc->bg_color, &bg_color);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
lv_draw_rect((lv_draw_ctx_t *) ctx, dsc, coords);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
256
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_composite.c
Normal file
256
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_composite.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_composite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_draw_sdl_composite_texture_id_t type;
|
||||
} composite_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type);
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num);
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in,
|
||||
const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out,
|
||||
lv_area_t * clip_out, lv_area_t * apply_area)
|
||||
{
|
||||
lv_area_t full_coords = *coords_in;
|
||||
|
||||
/* Normalize full_coords */
|
||||
if(full_coords.x1 > full_coords.x2) {
|
||||
lv_coord_t x2 = full_coords.x2;
|
||||
full_coords.x2 = full_coords.x1;
|
||||
full_coords.x1 = x2;
|
||||
}
|
||||
if(full_coords.y1 > full_coords.y2) {
|
||||
lv_coord_t y2 = full_coords.y2;
|
||||
full_coords.y2 = full_coords.y1;
|
||||
full_coords.y1 = y2;
|
||||
}
|
||||
|
||||
if(extension) {
|
||||
full_coords.x1 -= extension->x1;
|
||||
full_coords.x2 += extension->x2;
|
||||
full_coords.y1 -= extension->y1;
|
||||
full_coords.y2 += extension->y2;
|
||||
}
|
||||
|
||||
if(!_lv_area_intersect(apply_area, &full_coords, clip_in)) return false;
|
||||
bool has_mask = lv_draw_mask_is_any(apply_area);
|
||||
|
||||
const bool draw_mask = has_mask && LV_GPU_SDL_CUSTOM_BLEND_MODE;
|
||||
const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL;
|
||||
if(draw_mask || draw_blend) {
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
LV_ASSERT(internals->mask == NULL && internals->composition == NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area);
|
||||
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h);
|
||||
/* Don't need to worry about overflow */
|
||||
lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1;
|
||||
/* Offset draw area to start with (0,0) of coords */
|
||||
lv_area_move(coords_out, ofs_x, ofs_y);
|
||||
lv_area_move(clip_out, ofs_x, ofs_y);
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->composition);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0);
|
||||
SDL_RenderClear(ctx->renderer);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
internals->mask = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, w, h);
|
||||
dump_masks(internals->mask, apply_area);
|
||||
#endif
|
||||
}
|
||||
else if(has_mask) {
|
||||
/* Fallback mask handling. This will at least make bars looks less bad */
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(comm_param == NULL) continue;
|
||||
switch(comm_param->type) {
|
||||
case LV_DRAW_MASK_TYPE_RADIUS: {
|
||||
const lv_draw_mask_radius_param_t * param = (const lv_draw_mask_radius_param_t *) comm_param;
|
||||
if(param->cfg.outer) break;
|
||||
_lv_area_intersect(clip_out, apply_area, ¶m->cfg.rect);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return has_mask;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
SDL_Rect src_rect = {0, 0, lv_area_get_width(apply_area), lv_area_get_height(apply_area)};
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
if(internals->mask) {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->mask, mode);
|
||||
SDL_RenderCopy(ctx->renderer, internals->mask, &src_rect, &src_rect);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shapes are drawn on composite layer when mask or blend mode is present */
|
||||
if(internals->composition) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(apply_area, &dst_rect);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, ctx->base_draw.buf);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
break;
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_ADD);
|
||||
break;
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
case LV_BLEND_MODE_SUBTRACTIVE: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ONE,
|
||||
SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
case LV_BLEND_MODE_MULTIPLY: {
|
||||
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDFACTOR_DST_ALPHA, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(internals->composition, mode);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
LV_LOG_WARN("Doesn't support blend mode %d", blend_mode);
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
/* Unsupported yet */
|
||||
break;
|
||||
}
|
||||
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
|
||||
}
|
||||
|
||||
internals->mask = internals->composition = NULL;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
|
||||
lv_coord_t w, lv_coord_t h)
|
||||
{
|
||||
lv_point_t * tex_size = NULL;
|
||||
composite_key_t mask_key = mask_key_create(id);
|
||||
SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL,
|
||||
(void **) &tex_size);
|
||||
if(!result || tex_size->x < w || tex_size->y < h) {
|
||||
lv_coord_t size = next_pow_of_2(LV_MAX(w, h));
|
||||
int access = SDL_TEXTUREACCESS_STREAMING;
|
||||
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
|
||||
tex_size = lv_mem_alloc(sizeof(lv_point_t));
|
||||
tex_size->x = tex_size->y = size;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, tex_size, lv_mem_free, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type)
|
||||
{
|
||||
composite_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_MASK;
|
||||
key.type = type;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_coord_t next_pow_of_2(lv_coord_t num)
|
||||
{
|
||||
lv_coord_t n = 128;
|
||||
while(n < num && n < 16384) {
|
||||
n = n << 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
const size_t idx = y * pitch + x * 4;
|
||||
pixels[idx] = line_buf[x];
|
||||
pixels[idx + 1] = pixels[idx + 2] = pixels[idx + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
72
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_composite.h
Normal file
72
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_composite.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_composite.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_COMPOSITE_H
|
||||
#define LV_DRAW_SDL_COMPOSITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum lv_draw_sdl_composite_texture_id_t {
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1,
|
||||
} lv_draw_sdl_composite_texture_id_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Begin drawing with mask. Render target will be switched to a temporary texture,
|
||||
* and drawing coordinates may get clipped or translated
|
||||
* @param coords_in Original coordinates
|
||||
* @param clip_in Original clip area
|
||||
* @param extension Useful for shadows or outlines, can be NULL
|
||||
* @param coords_out Translated coords
|
||||
* @param clip_out Translated clip area
|
||||
* @param apply_area Area of actual composited texture will be drawn
|
||||
* @return true if there are any mask needs to be drawn, false otherwise
|
||||
*/
|
||||
bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in,
|
||||
const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out,
|
||||
lv_area_t * clip_out, lv_area_t * apply_area);
|
||||
|
||||
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
|
||||
lv_coord_t w, lv_coord_t h);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_COMPOSITE_H*/
|
||||
459
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_img.c
Normal file
459
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_img.c
Normal file
@@ -0,0 +1,459 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_img_cache.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../misc/lv_lru.h"
|
||||
#include "../../misc/lv_gc.h"
|
||||
|
||||
#include "lv_draw_sdl_img.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_rect.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const SDL_Texture * texture;
|
||||
lv_coord_t w, h, radius;
|
||||
} lv_draw_img_rounded_key_t;
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_PART_LEFT = 0,
|
||||
ROUNDED_IMG_PART_HCENTER = 1,
|
||||
ROUNDED_IMG_PART_RIGHT = 2,
|
||||
ROUNDED_IMG_PART_TOP = 3,
|
||||
ROUNDED_IMG_PART_VCENTER = 4,
|
||||
ROUNDED_IMG_PART_BOTTOM = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
ROUNDED_IMG_CORNER_TOP_LEFT = 0,
|
||||
ROUNDED_IMG_CORNER_TOP_RIGHT = 1,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_RIGHT = 2,
|
||||
ROUNDED_IMG_CORNER_BOTTOM_LEFT = 3,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius);
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip);
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius);
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius);
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius);
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const void * src)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
size_t key_size;
|
||||
lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(src, draw_dsc->frame_id, &key_size);
|
||||
bool texture_found = false;
|
||||
lv_draw_sdl_img_header_t * header = NULL;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found,
|
||||
(void **) &header);
|
||||
if(!texture_found) {
|
||||
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header);
|
||||
}
|
||||
SDL_free(key);
|
||||
if(!texture) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_area_t zoomed_cords;
|
||||
_lv_img_buf_get_transformed_area(&zoomed_cords, lv_area_get_width(coords), lv_area_get_height(coords), 0,
|
||||
draw_dsc->zoom, &draw_dsc->pivot);
|
||||
lv_area_move(&zoomed_cords, coords->x1, coords->y1);
|
||||
|
||||
/* When in > 0, draw simple radius */
|
||||
lv_coord_t radius = 0;
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area;
|
||||
|
||||
if(!check_mask_simple_radius(&t_coords, &radius)) {
|
||||
lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode,
|
||||
&t_coords, &t_clip, &apply_area);
|
||||
}
|
||||
|
||||
SDL_Rect clip_rect, coords_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
lv_area_to_sdl_rect(&t_coords, &coords_rect);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
if(radius > 0) {
|
||||
draw_img_rounded(ctx, texture, header, draw_dsc, &t_coords, &t_clip, radius);
|
||||
}
|
||||
else {
|
||||
draw_img_simple(ctx, texture, header, draw_dsc, &t_coords, &t_clip);
|
||||
}
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords,
|
||||
const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst)
|
||||
{
|
||||
double x = 0, y = 0, w, h;
|
||||
if(SDL_RectEmpty(&header->rect)) {
|
||||
Uint32 format = 0;
|
||||
int access = 0, tw, th;
|
||||
SDL_QueryTexture(texture, &format, &access, &tw, &th);
|
||||
w = tw;
|
||||
h = th;
|
||||
}
|
||||
else {
|
||||
x = header->rect.x;
|
||||
y = header->rect.y;
|
||||
w = header->rect.w;
|
||||
h = header->rect.h;
|
||||
}
|
||||
if(clip) {
|
||||
lv_area_t clipped_area;
|
||||
_lv_area_intersect(&clipped_area, coords, clip);
|
||||
lv_area_to_sdl_rect(&clipped_area, clipped_dst);
|
||||
}
|
||||
else {
|
||||
lv_area_to_sdl_rect(coords, clipped_dst);
|
||||
}
|
||||
lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords);
|
||||
clipped_src->x = (int)(x + (clipped_dst->x - coords->x1) * w / coords_w);
|
||||
clipped_src->y = (int)(y + (clipped_dst->y - coords->y1) * h / coords_h);
|
||||
clipped_src->w = (int)(w - (coords_w - clipped_dst->w) * w / coords_w);
|
||||
clipped_src->h = (int)(h - (coords_h - clipped_dst->h) * h / coords_h);
|
||||
}
|
||||
|
||||
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
|
||||
const void * src, int32_t frame_id, SDL_Texture ** texture,
|
||||
lv_draw_sdl_img_header_t ** header)
|
||||
{
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id);
|
||||
lv_draw_sdl_cache_flag_t tex_flags = 0;
|
||||
SDL_Rect rect;
|
||||
SDL_memset(&rect, 0, sizeof(SDL_Rect));
|
||||
if(cdsc) {
|
||||
lv_img_decoder_dsc_t * dsc = &cdsc->dec_dsc;
|
||||
if(dsc->user_data && SDL_memcmp(dsc->user_data, LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD, 8) == 0) {
|
||||
lv_draw_sdl_dec_dsc_userdata_t * ptr = (lv_draw_sdl_dec_dsc_userdata_t *) dsc->user_data;
|
||||
*texture = ptr->texture;
|
||||
rect = ptr->rect;
|
||||
if(ptr->texture_managed) {
|
||||
tex_flags |= LV_DRAW_SDL_CACHE_FLAG_MANAGED;
|
||||
}
|
||||
ptr->texture_referenced = true;
|
||||
}
|
||||
else {
|
||||
*texture = upload_img_texture(ctx->renderer, dsc);
|
||||
}
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(dsc);
|
||||
#endif
|
||||
}
|
||||
if(texture && cdsc) {
|
||||
*header = SDL_malloc(sizeof(lv_draw_sdl_img_header_t));
|
||||
SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t));
|
||||
(*header)->rect = rect;
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, tex_flags);
|
||||
}
|
||||
else {
|
||||
lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
if(!dsc->img_data) {
|
||||
return upload_img_texture_fallback(renderer, dsc);
|
||||
}
|
||||
bool chroma_keyed = dsc->header.cf == (uint32_t) LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
int h = (int) dsc->header.h;
|
||||
int w = (int) dsc->header.w;
|
||||
void * data = (void *) dsc->img_data;
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
if(chroma_keyed) {
|
||||
amask = 0x00;
|
||||
}
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, chroma_keyed, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
lv_coord_t h = (lv_coord_t) dsc->header.h;
|
||||
lv_coord_t w = (lv_coord_t) dsc->header.w;
|
||||
uint8_t * data = lv_mem_buf_get(w * h * sizeof(lv_color_t));
|
||||
for(lv_coord_t y = 0; y < h; y++) {
|
||||
lv_img_decoder_read_line(dsc, 0, y, w, &data[y * w * sizeof(lv_color_t)]);
|
||||
}
|
||||
Uint32 rmask = 0x00FF0000;
|
||||
Uint32 gmask = 0x0000FF00;
|
||||
Uint32 bmask = 0x000000FF;
|
||||
Uint32 amask = 0xFF000000;
|
||||
SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
SDL_SetColorKey(surface, SDL_TRUE, lv_color_to32(LV_COLOR_CHROMA_KEY));
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
lv_mem_buf_release(data);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is only one radius mask
|
||||
* @param radius Set to radius value if the only mask is a radius mask
|
||||
* @return true if the only mask is a radius mask
|
||||
*/
|
||||
static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius)
|
||||
{
|
||||
if(lv_draw_mask_get_cnt() != 1) return false;
|
||||
for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) {
|
||||
_lv_draw_mask_common_dsc_t * param = LV_GC_ROOT(_lv_draw_mask_list[i]).param;
|
||||
if(param->type == LV_DRAW_MASK_TYPE_RADIUS) {
|
||||
lv_draw_mask_radius_param_t * rparam = (lv_draw_mask_radius_param_t *) param;
|
||||
if(rparam->cfg.outer) return false;
|
||||
if(!_lv_area_is_equal(&rparam->cfg.rect, coords)) return false;
|
||||
*radius = rparam->cfg.radius;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip)
|
||||
{
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
SDL_Point pivot = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
|
||||
|
||||
/*Image needs to be rotated, so we have to use clip rect which is slower*/
|
||||
if(draw_dsc->angle != 0) {
|
||||
/* No radius, set clip here */
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(clip, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
}
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
calc_draw_part(texture, header, coords, clip, &src_rect, &dst_rect);
|
||||
SDL_RenderCopyEx(ctx->renderer, texture, &src_rect, &dst_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE);
|
||||
if(draw_dsc->angle != 0) {
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header,
|
||||
const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
const int w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_coord_t real_radius = LV_MIN3(radius, w, h);
|
||||
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius);
|
||||
apply_recolor_opa(frag, draw_dsc);
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true);
|
||||
|
||||
apply_recolor_opa(texture, draw_dsc);
|
||||
|
||||
SDL_Rect src_rect, dst_rect;
|
||||
/* Draw 3 parts */
|
||||
lv_area_t clip_tmp, part;
|
||||
calc_draw_part(texture, header, coords, NULL, &src_rect, &dst_rect);
|
||||
for(int i = w > h ? ROUNDED_IMG_PART_LEFT : ROUNDED_IMG_PART_TOP, j = i + 3; i <= j; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_PART_LEFT:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x1 + radius - 1, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_HCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_RIGHT:
|
||||
lv_area_set(&part, coords->x2 - radius + 1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_TOP:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y1 + radius - 1);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_VCENTER:
|
||||
lv_area_set(&part, coords->x1 + radius, coords->y2 - radius + 1, coords->x2 - radius, coords->y2);
|
||||
break;
|
||||
case ROUNDED_IMG_PART_BOTTOM:
|
||||
lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x2, coords->y2 - radius);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!_lv_area_intersect(&clip_tmp, &part, clip)) continue;
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&clip_tmp, &clip_rect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &clip_rect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
}
|
||||
|
||||
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_dsc->recolor_opa > LV_OPA_TRANSP) {
|
||||
/* Draw with mixed recolor */
|
||||
lv_color_t recolor = lv_color_mix(draw_dsc->recolor, lv_color_white(), draw_dsc->recolor_opa);
|
||||
SDL_SetTextureColorMod(texture, recolor.ch.red, recolor.ch.green, recolor.ch.blue);
|
||||
}
|
||||
else {
|
||||
/* Draw with no recolor */
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
SDL_SetTextureAlphaMod(texture, draw_dsc->opa);
|
||||
}
|
||||
|
||||
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
|
||||
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius);
|
||||
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius);
|
||||
SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(img_frag == NULL) {
|
||||
const lv_coord_t full_frag_size = radius * 2 + 3;
|
||||
img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
|
||||
full_frag_size, full_frag_size);
|
||||
SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND);
|
||||
SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, img_frag);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(ctx->renderer);
|
||||
|
||||
lv_area_t coords = {0, 0, w - 1, h - 1}, clip;
|
||||
lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1};
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false);
|
||||
|
||||
SDL_SetTextureAlphaMod(texture, 0xFF);
|
||||
SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF);
|
||||
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
|
||||
SDL_BlendMode blend_mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO,
|
||||
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_DST_ALPHA,
|
||||
SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD);
|
||||
SDL_SetTextureBlendMode(texture, blend_mode);
|
||||
#else
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD);
|
||||
#endif
|
||||
SDL_Rect srcrect, cliprect, dstrect = {0, 0, radius, radius};
|
||||
|
||||
cliprect.w = cliprect.h = radius;
|
||||
for(int i = 0; i <= ROUNDED_IMG_CORNER_BOTTOM_LEFT; i++) {
|
||||
switch(i) {
|
||||
case ROUNDED_IMG_CORNER_TOP_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_TOP_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = 0;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_RIGHT:
|
||||
cliprect.x = full_frag_size - radius;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
break;
|
||||
case ROUNDED_IMG_CORNER_BOTTOM_LEFT:
|
||||
cliprect.x = 0;
|
||||
cliprect.y = full_frag_size - radius;
|
||||
lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
calc_draw_part(texture, header, &coords, NULL, &srcrect, &dstrect);
|
||||
SDL_RenderSetClipRect(ctx->renderer, &cliprect);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
SDL_RenderSetClipRect(ctx->renderer, NULL);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, old_target);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
|
||||
}
|
||||
return img_frag;
|
||||
}
|
||||
|
||||
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
|
||||
lv_coord_t radius)
|
||||
{
|
||||
lv_draw_img_rounded_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS;
|
||||
key.texture = texture;
|
||||
key.w = w;
|
||||
key.h = h;
|
||||
key.radius = radius;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
72
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_img.h
Normal file
72
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_img.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_img.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_IMG_H
|
||||
#define LV_DRAW_SDL_IMG_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_img_header_t {
|
||||
lv_img_header_t base;
|
||||
SDL_Rect rect;
|
||||
} lv_draw_sdl_img_header_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
|
||||
const void * src, int32_t frame_id, SDL_Texture ** texture,
|
||||
lv_draw_sdl_img_header_t ** header);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_IMG_H*/
|
||||
173
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_label.c
Normal file
173
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_label.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../misc/lv_utils.h"
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
const lv_font_t * font_p;
|
||||
uint32_t letter;
|
||||
} lv_font_glyph_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter)
|
||||
{
|
||||
const lv_area_t * clip_area = draw_ctx->clip_area;
|
||||
const lv_font_t * font_p = dsc->font;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
lv_color_t color = dsc->color;
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
if(font_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: font is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_font_glyph_dsc_t g;
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
|
||||
if(g_ret == false) {
|
||||
/*Add warning if the dsc is not found
|
||||
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
|
||||
if(letter >= 0x20 &&
|
||||
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
|
||||
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
|
||||
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
|
||||
|
||||
/* draw placeholder */
|
||||
lv_area_t glyph_coords;
|
||||
lv_draw_rect_dsc_t glyph_dsc;
|
||||
lv_coord_t begin_x = pos_p->x + g.ofs_x;
|
||||
lv_coord_t begin_y = pos_p->y + g.ofs_y;
|
||||
lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h);
|
||||
lv_draw_rect_dsc_init(&glyph_dsc);
|
||||
glyph_dsc.bg_opa = LV_OPA_MIN;
|
||||
glyph_dsc.outline_opa = LV_OPA_MIN;
|
||||
glyph_dsc.shadow_opa = LV_OPA_MIN;
|
||||
glyph_dsc.bg_img_opa = LV_OPA_MIN;
|
||||
glyph_dsc.border_color = dsc->color;
|
||||
glyph_dsc.border_width = 1;
|
||||
draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*Don't draw anything if the character is empty. E.g. space*/
|
||||
if((g.box_h == 0) || (g.box_w == 0)) return;
|
||||
|
||||
int32_t pos_x = pos_p->x + g.ofs_x;
|
||||
int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
|
||||
|
||||
const lv_area_t letter_area = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1};
|
||||
lv_area_t draw_area;
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &letter_area, clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
|
||||
bool glyph_found = false;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found);
|
||||
if(!glyph_found) {
|
||||
if(g.resolved_font) {
|
||||
font_p = g.resolved_font;
|
||||
}
|
||||
const uint8_t * bmp = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
uint8_t * buf = lv_mem_alloc(g.box_w * g.box_h);
|
||||
lv_sdl_to_8bpp(buf, bmp, g.box_w, g.box_h, g.box_w, g.bpp);
|
||||
SDL_Surface * mask = lv_sdl_create_opa_surface(buf, g.box_w, g.box_h, g.box_w);
|
||||
texture = SDL_CreateTextureFromSurface(renderer, mask);
|
||||
SDL_FreeSurface(mask);
|
||||
lv_mem_free(buf);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
|
||||
}
|
||||
if(!texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area;
|
||||
bool has_mask = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter, &t_clip,
|
||||
&apply_area);
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect srcrect, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
srcrect.x = draw_area.x1 - t_letter.x1;
|
||||
srcrect.y = draw_area.y1 - t_letter.y1;
|
||||
srcrect.w = dstrect.w;
|
||||
srcrect.h = dstrect.h;
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue);
|
||||
SDL_RenderCopy(renderer, texture, &srcrect, &dstrect);
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter)
|
||||
{
|
||||
lv_font_glyph_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH;
|
||||
key.font_p = font_p;
|
||||
key.letter = letter;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
154
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_line.c
Normal file
154
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_line.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ROUND_START 0x01
|
||||
#define ROUND_END 0x02
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t length;
|
||||
lv_coord_t width;
|
||||
uint8_t round;
|
||||
} lv_draw_line_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length);
|
||||
|
||||
static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc,
|
||||
lv_coord_t length);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||
const lv_point_t * point2)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = sdl_ctx->renderer;
|
||||
lv_coord_t x1 = point1->x, x2 = point2->x, y1 = point1->y, y2 = point2->y;
|
||||
double length = SDL_sqrt(SDL_pow(x2 - x1, 2) + SDL_pow(y2 - y1, 2));
|
||||
if(length - (long) length > 0.5) {
|
||||
length = (long) length + 1;
|
||||
}
|
||||
|
||||
double angle = SDL_atan2(y2 - y1, x2 - x1) * 180 / M_PI;
|
||||
lv_draw_line_key_t key = line_key_create(dsc, (lv_coord_t) length);
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL);
|
||||
if(!texture) {
|
||||
texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length);
|
||||
lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
lv_area_t coords = {x1, y1, x2, y2};
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
|
||||
SDL_Rect coords_r, clip_r;
|
||||
lv_area_to_sdl_rect(&coords, &coords_r);
|
||||
lv_area_to_sdl_rect(clip, &clip_r);
|
||||
|
||||
lv_area_t t_coords = coords, t_clip = *clip, apply_area;
|
||||
lv_area_t extension = {dsc->width / 2, dsc->width / 2, dsc->width / 2, dsc->width / 2};
|
||||
lv_draw_sdl_composite_begin(sdl_ctx, &coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip,
|
||||
&apply_area);
|
||||
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&dsc->color, &color);
|
||||
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->opa);
|
||||
SDL_Rect srcrect = {0, 0, (int) length + dsc->width + 2, dsc->width + 2},
|
||||
dstrect = {t_coords.x1 - 1 - dsc->width / 2, t_coords.y1 - 1, srcrect.w, srcrect.h};
|
||||
SDL_Point center = {1 + dsc->width / 2, 1 + dsc->width / 2};
|
||||
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
if(!SDL_RectEquals(&clip_rect, &dstrect) || angle != 0) {
|
||||
SDL_RenderSetClipRect(renderer, &clip_rect);
|
||||
}
|
||||
SDL_RenderCopyEx(renderer, texture, &srcrect, &dstrect, angle, ¢er, 0);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
|
||||
lv_draw_sdl_composite_end(sdl_ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length)
|
||||
{
|
||||
lv_draw_line_key_t key;
|
||||
lv_memset_00(&key, sizeof(lv_draw_line_key_t));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_LINE;
|
||||
key.length = length;
|
||||
key.width = dsc->width;
|
||||
key.round = (dsc->round_start ? ROUND_START : 0) | (dsc->round_end ? ROUND_END : 0);
|
||||
return key;
|
||||
}
|
||||
|
||||
static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc, lv_coord_t length)
|
||||
{
|
||||
SDL_Texture * texture = SDL_CreateTexture(sdl_ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
|
||||
length + dsc->width + 2, dsc->width + 2);
|
||||
SDL_Texture * target = SDL_GetRenderTarget(sdl_ctx->renderer);
|
||||
SDL_SetRenderTarget(sdl_ctx->renderer, texture);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0x0);
|
||||
SDL_RenderClear(sdl_ctx->renderer);
|
||||
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
SDL_Rect line_rect = {1 + dsc->width / 2, 1, length, dsc->width};
|
||||
SDL_RenderFillRect(sdl_ctx->renderer, &line_rect);
|
||||
if(dsc->round_start || dsc->round_end) {
|
||||
lv_draw_mask_radius_param_t param;
|
||||
lv_area_t round_area = {0, 0, dsc->width - 1, dsc->width - 1};
|
||||
lv_draw_mask_radius_init(¶m, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
|
||||
int16_t mask_id = lv_draw_mask_add(¶m, NULL);
|
||||
SDL_Texture * round_texture = lv_draw_sdl_mask_dump_texture(sdl_ctx->renderer, &round_area, &mask_id, 1);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
|
||||
SDL_Rect round_src = {0, 0, dsc->width, dsc->width};
|
||||
SDL_Rect round_dst = {line_rect.x - dsc->width / 2, 1, dsc->width, dsc->width};
|
||||
SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
|
||||
round_dst.x = line_rect.w + dsc->width / 2;
|
||||
SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
|
||||
SDL_DestroyTexture(round_texture);
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(sdl_ctx->renderer, target);
|
||||
return texture;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
84
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_mask.c
Normal file
84
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_mask.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_mask.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef HAVE_SDL_CUSTOM_BLEND_MODE
|
||||
#define HAVE_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count)
|
||||
{
|
||||
SDL_assert(coords->x2 >= coords->x1);
|
||||
SDL_assert(coords->y2 >= coords->y1);
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(w * h);
|
||||
for(lv_coord_t y = 0; y < h; y++) {
|
||||
lv_opa_t * line_buf = &mask_buf[y * w];
|
||||
lv_memset_ff(line_buf, w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) w;
|
||||
lv_draw_mask_res_t res;
|
||||
if(ids) {
|
||||
res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count);
|
||||
}
|
||||
else {
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
}
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(line_buf, w);
|
||||
}
|
||||
}
|
||||
return mask_buf;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids,
|
||||
int16_t ids_count)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(coords, ids, ids_count);
|
||||
SDL_Surface * surface = lv_sdl_create_opa_surface(mask_buf, w, h, w);
|
||||
lv_mem_buf_release(mask_buf);
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
51
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_mask.h
Normal file
51
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_mask.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_mask.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_MASK_H
|
||||
#define LV_DRAW_SDL_MASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids,
|
||||
int16_t ids_count);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_MASK_H*/
|
||||
133
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c
Normal file
133
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_polygon.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points,
|
||||
uint16_t point_cnt)
|
||||
{
|
||||
if(point_cnt < 3) return;
|
||||
if(points == NULL) return;
|
||||
|
||||
lv_draw_mask_polygon_param_t polygon_param;
|
||||
lv_draw_mask_polygon_init(&polygon_param, points, point_cnt);
|
||||
|
||||
if(polygon_param.cfg.point_cnt < 3) {
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t poly_coords = {.x1 = LV_COORD_MAX, .y1 = LV_COORD_MAX, .x2 = LV_COORD_MIN, .y2 = LV_COORD_MIN};
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < point_cnt; i++) {
|
||||
poly_coords.x1 = LV_MIN(poly_coords.x1, polygon_param.cfg.points[i].x);
|
||||
poly_coords.y1 = LV_MIN(poly_coords.y1, polygon_param.cfg.points[i].y);
|
||||
poly_coords.x2 = LV_MAX(poly_coords.x2, polygon_param.cfg.points[i].x);
|
||||
poly_coords.y2 = LV_MAX(poly_coords.y2, polygon_param.cfg.points[i].y);
|
||||
}
|
||||
|
||||
bool is_common;
|
||||
lv_area_t draw_area;
|
||||
is_common = _lv_area_intersect(&draw_area, &poly_coords, draw_ctx->clip_area);
|
||||
if(!is_common) {
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
int16_t mask_id = lv_draw_mask_add(&polygon_param, NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
|
||||
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
dump_masks(texture, &draw_area);
|
||||
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
lv_draw_mask_free_param(&polygon_param);
|
||||
|
||||
SDL_Rect srcrect = {0, 0, w, h}, dstrect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dstrect);
|
||||
SDL_Color color;
|
||||
lv_color_to_sdl_color(&draw_dsc->bg_color, &color);
|
||||
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
|
||||
SDL_SetTextureAlphaMod(texture, draw_dsc->bg_opa);
|
||||
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void dump_masks(SDL_Texture * texture, const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords);
|
||||
SDL_assert(w > 0 && h > 0);
|
||||
SDL_Rect rect = {0, 0, w, h};
|
||||
uint8_t * pixels;
|
||||
int pitch;
|
||||
if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return;
|
||||
|
||||
lv_opa_t * line_buf = lv_mem_buf_get(rect.w);
|
||||
for(lv_coord_t y = 0; y < rect.h; y++) {
|
||||
lv_memset_ff(line_buf, rect.w);
|
||||
lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w;
|
||||
lv_draw_mask_res_t res;
|
||||
res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len);
|
||||
if(res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else if(res == LV_DRAW_MASK_RES_FULL_COVER) {
|
||||
lv_memset_ff(&pixels[y * pitch], 4 * rect.w);
|
||||
}
|
||||
else {
|
||||
for(int x = 0; x < rect.w; x++) {
|
||||
uint8_t * pixel = &pixels[y * pitch + x * 4];
|
||||
*pixel = line_buf[x];
|
||||
pixel[1] = pixel[2] = pixel[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(line_buf);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
70
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_priv.h
Normal file
70
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_priv.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_priv.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_PRIV_H
|
||||
#define LV_DRAW_SDL_PRIV_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../../misc/lv_lru.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_context_internals_t {
|
||||
lv_lru_t * texture_cache;
|
||||
SDL_Texture * mask;
|
||||
SDL_Texture * composition;
|
||||
} lv_draw_sdl_context_internals_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_PRIV_H*/
|
||||
708
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_rect.c
Normal file
708
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_rect.c
Normal file
@@ -0,0 +1,708 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../lv_draw_rect.h"
|
||||
#include "../lv_draw_img.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_stack_blur.h"
|
||||
#include "lv_draw_sdl_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t radius;
|
||||
lv_coord_t size;
|
||||
} lv_draw_rect_bg_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t radius;
|
||||
lv_coord_t size;
|
||||
lv_coord_t blur;
|
||||
} lv_draw_rect_shadow_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_coord_t rout, rin;
|
||||
lv_area_t offsets;
|
||||
} lv_draw_rect_border_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area,
|
||||
const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa,
|
||||
lv_blend_mode_t blend_mode);
|
||||
|
||||
static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full);
|
||||
|
||||
static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full);
|
||||
|
||||
static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size);
|
||||
|
||||
static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur);
|
||||
|
||||
static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area,
|
||||
const lv_area_t * inner_area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define SKIP_BORDER(dsc) ((dsc)->border_opa <= LV_OPA_MIN || (dsc)->border_width == 0 || (dsc)->border_side == LV_BORDER_SIDE_NONE || (dsc)->border_post)
|
||||
#define SKIP_SHADOW(dsc) ((dsc)->shadow_width == 0 || (dsc)->shadow_opa <= LV_OPA_MIN || ((dsc)->shadow_width == 1 && (dsc)->shadow_spread <= 0 && (dsc)->shadow_ofs_x == 0 && (dsc)->shadow_ofs_y == 0))
|
||||
#define SKIP_IMAGE(dsc) ((dsc)->bg_img_src == NULL || (dsc)->bg_img_opa <= LV_OPA_MIN)
|
||||
#define SKIP_OUTLINE(dsc) ((dsc)->outline_opa <= LV_OPA_MIN || (dsc)->outline_width == 0)
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||
{
|
||||
const lv_area_t * clip = draw_ctx->clip_area;
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
|
||||
lv_area_t extension = {0, 0, 0, 0};
|
||||
if(!SKIP_SHADOW(dsc)) {
|
||||
lv_coord_t ext = (lv_coord_t)(dsc->shadow_spread - dsc->shadow_width / 2 + 1);
|
||||
extension.x1 = LV_MAX(extension.x1, -dsc->shadow_ofs_x + ext);
|
||||
extension.x2 = LV_MAX(extension.x2, dsc->shadow_ofs_x + ext);
|
||||
extension.y1 = LV_MAX(extension.y1, -dsc->shadow_ofs_y + ext);
|
||||
extension.y2 = LV_MAX(extension.y2, dsc->shadow_ofs_y + ext);
|
||||
}
|
||||
if(!SKIP_OUTLINE(dsc)) {
|
||||
lv_coord_t ext = (lv_coord_t)(dsc->outline_pad - 1 + dsc->outline_width);
|
||||
extension.x1 = LV_MAX(extension.x1, ext);
|
||||
extension.x2 = LV_MAX(extension.x2, ext);
|
||||
extension.y1 = LV_MAX(extension.y1, ext);
|
||||
extension.y2 = LV_MAX(extension.y2, ext);
|
||||
}
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = *coords, t_clip = *clip, apply_area, t_area;
|
||||
lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, &apply_area);
|
||||
bool has_content = _lv_area_intersect(&t_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
draw_shadow(ctx, &t_coords, &t_clip, dsc);
|
||||
/* Shadows and outlines will also draw in extended area */
|
||||
if(has_content) {
|
||||
draw_bg_color(ctx, &t_coords, &t_area, dsc);
|
||||
draw_bg_img(ctx, &t_coords, &t_area, dsc);
|
||||
draw_border(ctx, &t_coords, &t_area, dsc);
|
||||
}
|
||||
draw_outline(ctx, &t_coords, &t_clip, dsc);
|
||||
|
||||
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius)
|
||||
{
|
||||
lv_draw_rect_bg_key_t key = rect_bg_key_create(radius, radius);
|
||||
lv_area_t coords = {0, 0, radius * 2 - 1, radius * 2 - 1};
|
||||
lv_area_t coords_frag = {0, 0, radius - 1, radius - 1};
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &coords, radius, false);
|
||||
int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
texture = lv_draw_sdl_mask_dump_texture(ctx->renderer, &coords_frag, &mask_id, 1);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clip, bool full)
|
||||
{
|
||||
if(!clip) clip = coords;
|
||||
lv_area_t corner_area, dst_area;
|
||||
/* Upper left */
|
||||
corner_area.x1 = coords->x1;
|
||||
corner_area.y1 = coords->y1;
|
||||
corner_area.x2 = coords->x1 + frag_size - 1;
|
||||
corner_area.y2 = coords->y1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {sx, sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
/* Upper right, clip right edge if too big */
|
||||
corner_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size);
|
||||
corner_area.x2 = coords->x2;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, dst_area.y1 - corner_area.y1, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
/* Lower right, clip bottom edge if too big */
|
||||
corner_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size);
|
||||
corner_area.y2 = coords->y2;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, frag_size + 3 + sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, corner_area.y2 - dst_area.y2, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
/* Lower left, right edge should not be clip */
|
||||
corner_area.x1 = coords->x1;
|
||||
corner_area.x2 = coords->x1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &corner_area, clip)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1),
|
||||
sy = (lv_coord_t)(dst_area.y1 - corner_area.y1);
|
||||
SDL_Rect src_rect = {sx, frag_size + 3 + sy, dw, dh};
|
||||
SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {dst_area.x1 - corner_area.x1, corner_area.y2 - dst_area.y2, dw, dh};
|
||||
SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->bg_opa == 0) {
|
||||
return;
|
||||
}
|
||||
SDL_Color bg_color;
|
||||
lv_color_to_sdl_color(&dsc->bg_color, &bg_color);
|
||||
lv_coord_t radius = dsc->radius;
|
||||
if(radius <= 0) {
|
||||
SDL_Rect rect;
|
||||
lv_area_to_sdl_rect(draw_area, &rect);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa);
|
||||
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderFillRect(ctx->renderer, &rect);
|
||||
return;
|
||||
}
|
||||
|
||||
/*A small texture with a quarter of the rect is enough*/
|
||||
lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords);
|
||||
lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius);
|
||||
SDL_Texture * texture = lv_draw_sdl_rect_bg_frag_obtain(ctx, real_radius);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, dsc->bg_opa);
|
||||
SDL_SetTextureColorMod(texture, bg_color.r, bg_color.g, bg_color.b);
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, real_radius, coords, draw_area, false);
|
||||
frag_render_borders(ctx->renderer, texture, real_radius, coords, draw_area, false);
|
||||
frag_render_center(ctx->renderer, texture, real_radius, coords, draw_area, false);
|
||||
}
|
||||
|
||||
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_IMAGE(dsc)) return;
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src);
|
||||
if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_point_t size;
|
||||
lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
|
||||
lv_area_t a;
|
||||
a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2;
|
||||
a.x2 = a.x1 + size.x - 1;
|
||||
a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2;
|
||||
a.y2 = a.y1 + size.y - 1;
|
||||
|
||||
lv_draw_label_dsc_t label_draw_dsc;
|
||||
lv_draw_label_dsc_init(&label_draw_dsc);
|
||||
label_draw_dsc.font = dsc->bg_img_symbol_font;
|
||||
label_draw_dsc.color = dsc->bg_img_recolor;
|
||||
label_draw_dsc.opa = dsc->bg_img_opa;
|
||||
lv_draw_label((lv_draw_ctx_t *) ctx, &label_draw_dsc, &a, dsc->bg_img_src, NULL);
|
||||
}
|
||||
else {
|
||||
lv_img_header_t header;
|
||||
size_t key_size;
|
||||
lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(dsc->bg_img_src, 0, &key_size);
|
||||
bool key_found;
|
||||
lv_img_header_t * cache_header = NULL;
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &key_found,
|
||||
(void **) &cache_header);
|
||||
SDL_free(key);
|
||||
if(texture) {
|
||||
header = *cache_header;
|
||||
}
|
||||
else if(key_found || lv_img_decoder_get_info(dsc->bg_img_src, &header) != LV_RES_OK) {
|
||||
/* When cache hit but with negative result, use default decoder. If still fail, return.*/
|
||||
LV_LOG_WARN("Couldn't read the background image");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_draw_img_dsc_t img_dsc;
|
||||
lv_draw_img_dsc_init(&img_dsc);
|
||||
img_dsc.blend_mode = dsc->blend_mode;
|
||||
img_dsc.recolor = dsc->bg_img_recolor;
|
||||
img_dsc.recolor_opa = dsc->bg_img_recolor_opa;
|
||||
img_dsc.opa = dsc->bg_img_opa;
|
||||
img_dsc.frame_id = 0;
|
||||
|
||||
int16_t radius_mask_id = LV_MASK_ID_INV;
|
||||
lv_draw_mask_radius_param_t radius_param;
|
||||
if(dsc->radius > 0) {
|
||||
lv_draw_mask_radius_init(&radius_param, coords, dsc->radius, false);
|
||||
radius_mask_id = lv_draw_mask_add(&radius_param, NULL);
|
||||
}
|
||||
|
||||
/*Center align*/
|
||||
if(dsc->bg_img_tiled == false) {
|
||||
lv_area_t area;
|
||||
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2;
|
||||
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2;
|
||||
area.x2 = area.x1 + header.w - 1;
|
||||
area.y2 = area.y1 + header.h - 1;
|
||||
|
||||
lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src);
|
||||
}
|
||||
else {
|
||||
lv_area_t area;
|
||||
area.y1 = coords->y1;
|
||||
area.y2 = area.y1 + header.h - 1;
|
||||
|
||||
for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) {
|
||||
|
||||
area.x1 = coords->x1;
|
||||
area.x2 = area.x1 + header.w - 1;
|
||||
for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) {
|
||||
lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(radius_mask_id != LV_MASK_ID_INV) {
|
||||
lv_draw_mask_remove_id(radius_mask_id);
|
||||
lv_draw_mask_free_param(&radius_param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
/*Check whether the shadow is visible*/
|
||||
if(SKIP_SHADOW(dsc)) return;
|
||||
|
||||
lv_coord_t sw = dsc->shadow_width;
|
||||
|
||||
lv_area_t core_area;
|
||||
core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread;
|
||||
core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread;
|
||||
core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread;
|
||||
core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread;
|
||||
|
||||
lv_area_t shadow_area;
|
||||
shadow_area.x1 = core_area.x1 - sw / 2 - 1;
|
||||
shadow_area.x2 = core_area.x2 + sw / 2 + 1;
|
||||
shadow_area.y1 = core_area.y1 - sw / 2 - 1;
|
||||
shadow_area.y2 = core_area.y2 + sw / 2 + 1;
|
||||
|
||||
lv_opa_t opa = dsc->shadow_opa;
|
||||
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
/*Get clipped draw area which is the real draw area.
|
||||
*It is always the same or inside `shadow_area`*/
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &shadow_area, clip)) return;
|
||||
|
||||
SDL_Rect core_area_rect;
|
||||
lv_area_to_sdl_rect(&shadow_area, &core_area_rect);
|
||||
|
||||
lv_coord_t radius = dsc->radius;
|
||||
/* No matter how big the shadow is, what we need is just a corner */
|
||||
lv_coord_t frag_size = LV_MIN3(lv_area_get_width(&core_area) / 2, lv_area_get_height(&core_area) / 2,
|
||||
LV_MAX(sw / 2, radius));
|
||||
|
||||
/* This is how big the corner is after blurring */
|
||||
lv_coord_t blur_growth = (lv_coord_t)(sw / 2 + 1);
|
||||
|
||||
lv_coord_t blur_frag_size = (lv_coord_t)(frag_size + blur_growth);
|
||||
|
||||
lv_draw_rect_shadow_key_t key = rect_shadow_key_create(radius, frag_size, sw);
|
||||
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
lv_area_t mask_area = {blur_growth, blur_growth}, mask_area_blurred = {0, 0};
|
||||
lv_area_set_width(&mask_area, frag_size * 2);
|
||||
lv_area_set_height(&mask_area, frag_size * 2);
|
||||
lv_area_set_width(&mask_area_blurred, blur_frag_size * 2);
|
||||
lv_area_set_height(&mask_area_blurred, blur_frag_size * 2);
|
||||
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &mask_area, radius, false);
|
||||
int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(&mask_area_blurred, &mask_id, 1);
|
||||
lv_stack_blur_grayscale(mask_buf, lv_area_get_width(&mask_area_blurred), lv_area_get_height(&mask_area_blurred),
|
||||
sw / 2 + sw % 2);
|
||||
texture = lv_sdl_create_opa_texture(ctx->renderer, mask_buf, blur_frag_size, blur_frag_size,
|
||||
lv_area_get_width(&mask_area_blurred));
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_draw_mask_remove_id(mask_id);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
SDL_Color shadow_color;
|
||||
lv_color_to_sdl_color(&dsc->shadow_color, &shadow_color);
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, shadow_color.r, shadow_color.g, shadow_color.b);
|
||||
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
frag_render_borders(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
frag_render_center(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
|
||||
}
|
||||
|
||||
|
||||
static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_BORDER(dsc)) return;
|
||||
|
||||
SDL_Color border_color;
|
||||
lv_color_to_sdl_color(&dsc->border_color, &border_color);
|
||||
|
||||
lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords);
|
||||
lv_coord_t short_side = LV_MIN(coords_w, coords_h);
|
||||
lv_coord_t rout = LV_MIN(dsc->radius, short_side / 2);/*Get the inner area*/
|
||||
lv_area_t area_inner;
|
||||
lv_area_copy(&area_inner, coords);// lv_area_increase(&area_inner, 1, 1);
|
||||
area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : -(dsc->border_width + rout));
|
||||
lv_coord_t rin = LV_MAX(rout - dsc->border_width, 0);
|
||||
draw_border_generic(ctx, coords, &area_inner, draw_area, rout, rin, dsc->border_color, dsc->border_opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
|
||||
static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip,
|
||||
const lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
if(SKIP_OUTLINE(dsc)) return;
|
||||
|
||||
lv_opa_t opa = dsc->outline_opa;
|
||||
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
/*Get the inner radius*/
|
||||
lv_area_t area_inner;
|
||||
lv_area_copy(&area_inner, coords);
|
||||
|
||||
/*Bring the outline closer to make sure there is no color bleeding with pad=0*/
|
||||
lv_coord_t pad = dsc->outline_pad - 1;
|
||||
area_inner.x1 -= pad;
|
||||
area_inner.y1 -= pad;
|
||||
area_inner.x2 += pad;
|
||||
area_inner.y2 += pad;
|
||||
|
||||
lv_area_t area_outer;
|
||||
lv_area_copy(&area_outer, &area_inner);
|
||||
|
||||
area_outer.x1 -= dsc->outline_width;
|
||||
area_outer.x2 += dsc->outline_width;
|
||||
area_outer.y1 -= dsc->outline_width;
|
||||
area_outer.y2 += dsc->outline_width;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_outer, clip)) return;
|
||||
|
||||
int32_t inner_w = lv_area_get_width(&area_inner);
|
||||
int32_t inner_h = lv_area_get_height(&area_inner);
|
||||
lv_coord_t rin = dsc->radius;
|
||||
int32_t short_side = LV_MIN(inner_w, inner_h);
|
||||
if(rin > short_side >> 1) rin = short_side >> 1;
|
||||
|
||||
lv_coord_t rout = rin + dsc->outline_width;
|
||||
|
||||
draw_border_generic(ctx, &area_outer, &area_inner, clip, rout, rin, dsc->outline_color, dsc->outline_opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
|
||||
static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area,
|
||||
const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa,
|
||||
lv_blend_mode_t blend_mode)
|
||||
{
|
||||
opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa;
|
||||
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_draw_rect_border_key_t key = rect_border_key_create(rout, rin, outer_area, inner_area);
|
||||
lv_coord_t radius = LV_MIN3(rout, lv_area_get_width(outer_area) / 2, lv_area_get_height(outer_area) / 2);
|
||||
lv_coord_t max_side = LV_MAX4(key.offsets.x1, key.offsets.y1, -key.offsets.x2, -key.offsets.y2);
|
||||
lv_coord_t frag_size = LV_MAX(radius, max_side);
|
||||
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
|
||||
if(texture == NULL) {
|
||||
/* Create a mask texture with size of (frag_size * 2 + 3) */
|
||||
const lv_area_t frag_area = {0, 0, frag_size * 2 + 2, frag_size * 2 + 2};
|
||||
|
||||
/*Create mask for the outer area*/
|
||||
int16_t mask_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV};
|
||||
lv_draw_mask_radius_param_t mask_rout_param;
|
||||
if(rout > 0) {
|
||||
lv_draw_mask_radius_init(&mask_rout_param, &frag_area, rout, false);
|
||||
mask_ids[0] = lv_draw_mask_add(&mask_rout_param, NULL);
|
||||
}
|
||||
|
||||
/*Create mask for the inner mask*/
|
||||
if(rin < 0) rin = 0;
|
||||
const lv_area_t frag_inner_area = {frag_area.x1 + key.offsets.x1, frag_area.y1 + key.offsets.y1,
|
||||
frag_area.x2 + key.offsets.x2, frag_area.y2 + key.offsets.y2
|
||||
};
|
||||
lv_draw_mask_radius_param_t mask_rin_param;
|
||||
lv_draw_mask_radius_init(&mask_rin_param, &frag_inner_area, rin, true);
|
||||
mask_ids[1] = lv_draw_mask_add(&mask_rin_param, NULL);
|
||||
|
||||
texture = lv_draw_sdl_mask_dump_texture(renderer, &frag_area, mask_ids, 2);
|
||||
|
||||
lv_draw_mask_remove_id(mask_ids[1]);
|
||||
lv_draw_mask_remove_id(mask_ids[0]);
|
||||
SDL_assert(texture);
|
||||
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
|
||||
}
|
||||
|
||||
SDL_Rect outer_rect;
|
||||
lv_area_to_sdl_rect(outer_area, &outer_rect);
|
||||
SDL_Color color_sdl;
|
||||
lv_color_to_sdl_color(&color, &color_sdl);
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color_sdl.r, color_sdl.g, color_sdl.b);
|
||||
|
||||
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, frag_size, outer_area, clip, true);
|
||||
frag_render_borders(renderer, texture, frag_size, outer_area, clip, true);
|
||||
}
|
||||
|
||||
static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clipped, bool full)
|
||||
{
|
||||
lv_area_t border_area, dst_area;
|
||||
/* Top border */
|
||||
border_area.x1 = coords->x1 + frag_size;
|
||||
border_area.y1 = coords->y1;
|
||||
border_area.x2 = coords->x2 - frag_size;
|
||||
border_area.y2 = coords->y1 + frag_size - 1;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {frag_size + 1, sy, 1, lv_area_get_height(&dst_area)};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {frag_size - 1, sy, 1, lv_area_get_height(&dst_area)};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
/* Bottom border */
|
||||
border_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size);
|
||||
border_area.y2 = coords->y2;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dh = lv_area_get_height(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1);
|
||||
SDL_Rect src_rect = {frag_size + 1, frag_size + 3 + sy, 1, dh};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
lv_coord_t sy = (lv_coord_t)(border_area.y2 - dst_area.y2);
|
||||
SDL_Rect src_rect = {frag_size - 1, sy, 1, dh};
|
||||
SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
}
|
||||
/* Left border */
|
||||
border_area.x1 = coords->x1;
|
||||
border_area.y1 = coords->y1 + frag_size;
|
||||
border_area.x2 = coords->x1 + frag_size - 1;
|
||||
border_area.y2 = coords->y2 - frag_size;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area);
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {sx, frag_size + 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {sx, frag_size - 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
/* Right border */
|
||||
border_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size);
|
||||
border_area.x2 = coords->x2;
|
||||
if(_lv_area_intersect(&dst_area, &border_area, clipped)) {
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&dst_area, &dst_rect);
|
||||
|
||||
lv_coord_t dw = lv_area_get_width(&dst_area);
|
||||
if(full) {
|
||||
lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1);
|
||||
SDL_Rect src_rect = {frag_size + 3 + sx, frag_size + 1, dw, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
lv_coord_t sx = (lv_coord_t)(border_area.x2 - dst_area.x2);
|
||||
SDL_Rect src_rect = {sx, frag_size - 1, dw, 1};
|
||||
SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords,
|
||||
const lv_area_t * clipped, bool full)
|
||||
{
|
||||
lv_area_t center_area = {
|
||||
coords->x1 + frag_size,
|
||||
coords->y1 + frag_size,
|
||||
coords->x2 - frag_size,
|
||||
coords->y2 - frag_size,
|
||||
};
|
||||
if(center_area.x2 < center_area.x1 || center_area.y2 < center_area.y1) return;
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, ¢er_area, clipped)) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(&draw_area, &dst_rect);
|
||||
if(full) {
|
||||
SDL_Rect src_rect = {frag_size, frag_size, 1, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
else {
|
||||
SDL_Rect src_rect = {frag_size - 1, frag_size - 1, 1, 1};
|
||||
SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect);
|
||||
}
|
||||
}
|
||||
|
||||
static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size)
|
||||
{
|
||||
lv_draw_rect_bg_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BG;
|
||||
key.radius = radius;
|
||||
key.size = size;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur)
|
||||
{
|
||||
lv_draw_rect_shadow_key_t key;
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW;
|
||||
key.radius = radius;
|
||||
key.size = size;
|
||||
key.blur = blur;
|
||||
return key;
|
||||
}
|
||||
|
||||
static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area,
|
||||
const lv_area_t * inner_area)
|
||||
{
|
||||
lv_draw_rect_border_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER;
|
||||
key.rout = rout;
|
||||
key.rin = rin;
|
||||
key.offsets.x1 = inner_area->x1 - outer_area->x1;
|
||||
key.offsets.x2 = inner_area->x2 - outer_area->x2;
|
||||
key.offsets.y1 = inner_area->y1 - outer_area->y1;
|
||||
key.offsets.y2 = inner_area->y2 - outer_area->y2;
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
75
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_rect.h
Normal file
75
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_rect.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_RECT_H
|
||||
#define LV_DRAW_SDL_RECT_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
#include "../lv_draw.h"
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_sdl_rect_header_t {
|
||||
lv_img_header_t base;
|
||||
SDL_Rect rect;
|
||||
} lv_draw_sdl_rect_header_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius);
|
||||
|
||||
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
|
||||
const lv_area_t * coords, const lv_area_t * clip, bool full);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_RECT_H*/
|
||||
249
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c
Normal file
249
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_stack_blur.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sdl_stack_blur.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void
|
||||
stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, int step);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
// Based heavily on http://vitiy.info/Code/stackblur.cpp
|
||||
// See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/
|
||||
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
|
||||
|
||||
static unsigned short const stackblur_mul[255] = {
|
||||
512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,
|
||||
454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,
|
||||
482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,
|
||||
437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,
|
||||
497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,
|
||||
320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,
|
||||
446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,
|
||||
329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,
|
||||
505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,
|
||||
399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,
|
||||
324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,
|
||||
268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,
|
||||
451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,
|
||||
385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,
|
||||
332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
|
||||
289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259
|
||||
};
|
||||
|
||||
static unsigned char const stackblur_shr[255] = {
|
||||
9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
|
||||
17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
|
||||
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r)
|
||||
{
|
||||
stack_blur_job(buf, w, h, r, 1, 0, 1);
|
||||
stack_blur_job(buf, w, h, r, 1, 0, 2);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core,
|
||||
int step)
|
||||
{
|
||||
if(radius < 2 || radius > 254) {
|
||||
/* Silently ignore bad radius */
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int x, y, xp, yp, i;
|
||||
unsigned int sp;
|
||||
unsigned int stack_start;
|
||||
unsigned char * stack_ptr;
|
||||
|
||||
lv_opa_t * src_ptr;
|
||||
lv_opa_t * dst_ptr;
|
||||
|
||||
unsigned long sum_r;
|
||||
unsigned long sum_in_r;
|
||||
unsigned long sum_out_r;
|
||||
|
||||
unsigned int wm = w - 1;
|
||||
unsigned int hm = h - 1;
|
||||
unsigned int stride = w;
|
||||
unsigned int div = (radius * 2) + 1;
|
||||
unsigned int mul_sum = stackblur_mul[radius];
|
||||
unsigned char shr_sum = stackblur_shr[radius];
|
||||
unsigned char stack[254 * 2 + 1];
|
||||
|
||||
if(step == 1) {
|
||||
unsigned int minY = core * h / cores;
|
||||
unsigned int maxY = (core + 1) * h / cores;
|
||||
|
||||
for(y = minY; y < maxY; y++) {
|
||||
sum_r =
|
||||
sum_in_r =
|
||||
sum_out_r = 0;
|
||||
|
||||
src_ptr = src + stride * y; // start of line (0,y)
|
||||
|
||||
for(i = 0; i <= radius; i++) {
|
||||
stack_ptr = &stack[i];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (i + 1);
|
||||
sum_out_r += src_ptr[0];
|
||||
}
|
||||
|
||||
|
||||
for(i = 1; i <= radius; i++) {
|
||||
if(i <= wm) src_ptr += 1;
|
||||
stack_ptr = &stack[i + radius];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (radius + 1 - i);
|
||||
sum_in_r += src_ptr[0];
|
||||
}
|
||||
|
||||
|
||||
sp = radius;
|
||||
xp = radius;
|
||||
if(xp > wm) xp = wm;
|
||||
src_ptr = src + (xp + y * w); // img.pix_ptr(xp, y);
|
||||
dst_ptr = src + y * stride; // img.pix_ptr(0, y);
|
||||
for(x = 0; x < w; x++) {
|
||||
dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255);
|
||||
dst_ptr += 1;
|
||||
|
||||
sum_r -= sum_out_r;
|
||||
|
||||
stack_start = sp + div - radius;
|
||||
if(stack_start >= div) stack_start -= div;
|
||||
stack_ptr = &stack[stack_start];
|
||||
|
||||
sum_out_r -= stack_ptr[0];
|
||||
|
||||
if(xp < wm) {
|
||||
src_ptr += 1;
|
||||
++xp;
|
||||
}
|
||||
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
|
||||
sum_in_r += src_ptr[0];
|
||||
sum_r += sum_in_r;
|
||||
|
||||
++sp;
|
||||
if(sp >= div) sp = 0;
|
||||
stack_ptr = &stack[sp];
|
||||
|
||||
sum_out_r += stack_ptr[0];
|
||||
sum_in_r -= stack_ptr[0];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// step 2
|
||||
if(step == 2) {
|
||||
unsigned int minX = core * w / cores;
|
||||
unsigned int maxX = (core + 1) * w / cores;
|
||||
|
||||
for(x = minX; x < maxX; x++) {
|
||||
sum_r =
|
||||
sum_in_r =
|
||||
sum_out_r = 0;
|
||||
|
||||
src_ptr = src + x; // x,0
|
||||
for(i = 0; i <= radius; i++) {
|
||||
stack_ptr = &stack[i];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (i + 1);
|
||||
sum_out_r += src_ptr[0];
|
||||
}
|
||||
for(i = 1; i <= radius; i++) {
|
||||
if(i <= hm) src_ptr += stride; // +stride
|
||||
|
||||
stack_ptr = &stack[i + radius];
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
sum_r += src_ptr[0] * (radius + 1 - i);
|
||||
sum_in_r += src_ptr[0];
|
||||
}
|
||||
|
||||
sp = radius;
|
||||
yp = radius;
|
||||
if(yp > hm) yp = hm;
|
||||
src_ptr = src + (x + yp * w); // img.pix_ptr(x, yp);
|
||||
dst_ptr = src + x; // img.pix_ptr(x, 0);
|
||||
for(y = 0; y < h; y++) {
|
||||
dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255);
|
||||
dst_ptr += stride;
|
||||
|
||||
sum_r -= sum_out_r;
|
||||
|
||||
stack_start = sp + div - radius;
|
||||
if(stack_start >= div) stack_start -= div;
|
||||
stack_ptr = &stack[stack_start];
|
||||
|
||||
sum_out_r -= stack_ptr[0];
|
||||
|
||||
if(yp < hm) {
|
||||
src_ptr += stride; // stride
|
||||
++yp;
|
||||
}
|
||||
|
||||
stack_ptr[0] = src_ptr[0];
|
||||
|
||||
sum_in_r += src_ptr[0];
|
||||
sum_r += sum_in_r;
|
||||
|
||||
++sp;
|
||||
if(sp >= div) sp = 0;
|
||||
stack_ptr = &stack[sp];
|
||||
|
||||
sum_out_r += stack_ptr[0];
|
||||
sum_in_r -= stack_ptr[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
46
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h
Normal file
46
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_stack_blur.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_DRAW_SDL_STACK_BLUR_H
|
||||
#define LV_DRAW_SDL_STACK_BLUR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_STACK_BLUR_H*/
|
||||
178
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c
Normal file
178
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_texture_cache.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
SDL_Texture * texture;
|
||||
void * userdata;
|
||||
lv_lru_free_t * userdata_free;
|
||||
lv_draw_sdl_cache_flag_t flags;
|
||||
} draw_cache_value_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
} temp_texture_key_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t width, height;
|
||||
} temp_texture_userdata_t;
|
||||
|
||||
static void draw_cache_free_value(draw_cache_value_t *);
|
||||
|
||||
static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx)
|
||||
{
|
||||
ctx->internals->texture_cache = lv_lru_create(LV_GPU_SDL_LRU_SIZE, 65536,
|
||||
(lv_lru_free_t *) draw_cache_free_value, NULL);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx)
|
||||
{
|
||||
lv_lru_del(ctx->internals->texture_cache);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found)
|
||||
{
|
||||
return lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_length, found, NULL);
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found, void ** userdata)
|
||||
{
|
||||
draw_cache_value_t * value = draw_cache_get_entry(ctx, key, key_length, found);
|
||||
if(!value) return NULL;
|
||||
if(userdata) {
|
||||
*userdata = value->userdata;
|
||||
}
|
||||
return value->texture;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture)
|
||||
{
|
||||
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
SDL_Texture * texture, void * userdata, void userdata_free(void *),
|
||||
lv_draw_sdl_cache_flag_t flags)
|
||||
{
|
||||
lv_lru_t * lru = ctx->internals->texture_cache;
|
||||
draw_cache_value_t * value = SDL_malloc(sizeof(draw_cache_value_t));
|
||||
value->texture = texture;
|
||||
value->userdata = userdata;
|
||||
value->userdata_free = userdata_free;
|
||||
value->flags = flags;
|
||||
if(!texture) {
|
||||
lv_lru_set(lru, key, key_length, value, 1);
|
||||
return;
|
||||
}
|
||||
if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) {
|
||||
/* Managed texture doesn't count into cache size */
|
||||
LV_LOG_INFO("cache texture %p", texture);
|
||||
lv_lru_set(lru, key, key_length, value, 1);
|
||||
return;
|
||||
}
|
||||
Uint32 format;
|
||||
int access, width, height;
|
||||
if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) {
|
||||
return;
|
||||
}
|
||||
LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format));
|
||||
lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8);
|
||||
}
|
||||
|
||||
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, size_t * size)
|
||||
{
|
||||
lv_draw_sdl_cache_key_head_img_t header;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&header, 0, sizeof(header));
|
||||
header.magic = LV_GPU_CACHE_KEY_MAGIC_IMG;
|
||||
header.type = lv_img_src_get_type(src);
|
||||
header.frame_id = frame_id;
|
||||
void * key;
|
||||
size_t key_size;
|
||||
if(header.type == LV_IMG_SRC_FILE || header.type == LV_IMG_SRC_SYMBOL) {
|
||||
size_t srclen = SDL_strlen(src);
|
||||
key_size = sizeof(header) + srclen;
|
||||
key = SDL_malloc(key_size);
|
||||
SDL_memcpy(key, &header, sizeof(header));
|
||||
/*Copy string content as key value*/
|
||||
SDL_memcpy(key + sizeof(header), src, srclen);
|
||||
}
|
||||
else {
|
||||
key_size = sizeof(header) + sizeof(void *);
|
||||
key = SDL_malloc(key_size);
|
||||
SDL_memcpy(key, &header, sizeof(header));
|
||||
/*Copy address number as key value*/
|
||||
SDL_memcpy(key + sizeof(header), &src, sizeof(void *));
|
||||
}
|
||||
*size = key_size;
|
||||
return (lv_draw_sdl_cache_key_head_img_t *) key;
|
||||
}
|
||||
|
||||
static void draw_cache_free_value(draw_cache_value_t * value)
|
||||
{
|
||||
if(value->texture && !(value->flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED)) {
|
||||
LV_LOG_INFO("destroy texture %p", value->texture);
|
||||
SDL_DestroyTexture(value->texture);
|
||||
}
|
||||
if(value->userdata_free) {
|
||||
value->userdata_free(value->userdata);
|
||||
}
|
||||
SDL_free(value);
|
||||
}
|
||||
|
||||
static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found)
|
||||
{
|
||||
lv_lru_t * lru = ctx->internals->texture_cache;
|
||||
draw_cache_value_t * value = NULL;
|
||||
lv_lru_get(lru, key, key_length, (void **) &value);
|
||||
if(!value) {
|
||||
if(found) {
|
||||
*found = false;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if(found) {
|
||||
*found = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
102
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h
Normal file
102
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_texture_cache.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SDL_TEXTURE_CACHE_H
|
||||
#define LV_DRAW_SDL_TEXTURE_CACHE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "../../draw/lv_img_decoder.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
char head[8];
|
||||
SDL_Texture * texture;
|
||||
SDL_Rect rect;
|
||||
bool texture_managed;
|
||||
bool texture_referenced;
|
||||
} lv_draw_sdl_dec_dsc_userdata_t;
|
||||
|
||||
typedef enum {
|
||||
LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01,
|
||||
LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11,
|
||||
LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS = 0x12,
|
||||
LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33,
|
||||
LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41,
|
||||
LV_GPU_CACHE_KEY_MAGIC_MASK = 0x51,
|
||||
} lv_sdl_cache_key_magic_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_SDL_CACHE_FLAG_NONE = 0,
|
||||
LV_DRAW_SDL_CACHE_FLAG_MANAGED = 1,
|
||||
} lv_draw_sdl_cache_flag_t;
|
||||
|
||||
typedef struct {
|
||||
lv_sdl_cache_key_magic_t magic;
|
||||
lv_img_src_t type;
|
||||
int32_t frame_id;
|
||||
} lv_draw_sdl_cache_key_head_img_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx);
|
||||
|
||||
void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx);
|
||||
|
||||
/**
|
||||
* Find cached texture by key. The texture can be destroyed during usage.
|
||||
*/
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found);
|
||||
|
||||
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
bool * found, void ** userdata);
|
||||
|
||||
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture);
|
||||
|
||||
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
|
||||
SDL_Texture * texture, void * userdata, void userdata_free(void *),
|
||||
lv_draw_sdl_cache_flag_t flags);
|
||||
|
||||
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id,
|
||||
size_t * size);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_TEXTURE_CACHE_H*/
|
||||
183
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_utils.c
Normal file
183
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_utils.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
|
||||
#include "../lv_draw.h"
|
||||
#include "../lv_draw_label.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
extern const uint8_t _lv_bpp1_opa_table[2];
|
||||
extern const uint8_t _lv_bpp2_opa_table[4];
|
||||
extern const uint8_t _lv_bpp4_opa_table[16];
|
||||
extern const uint8_t _lv_bpp8_opa_table[256];
|
||||
|
||||
static int utils_init_count = 0;
|
||||
static SDL_Palette * lv_sdl_palette_grayscale8 = NULL;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_draw_sdl_utils_init()
|
||||
{
|
||||
utils_init_count++;
|
||||
if(utils_init_count > 1) {
|
||||
return;
|
||||
}
|
||||
lv_sdl_palette_grayscale8 = lv_sdl_alloc_palette_for_bpp(_lv_bpp8_opa_table, 8);
|
||||
}
|
||||
|
||||
void _lv_draw_sdl_utils_deinit()
|
||||
{
|
||||
if(utils_init_count == 0) {
|
||||
return;
|
||||
}
|
||||
utils_init_count--;
|
||||
if(utils_init_count == 0) {
|
||||
SDL_FreePalette(lv_sdl_palette_grayscale8);
|
||||
lv_sdl_palette_grayscale8 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out)
|
||||
{
|
||||
out->x = in->x1;
|
||||
out->y = in->y1;
|
||||
out->w = in->x2 - in->x1 + 1;
|
||||
out->h = in->y2 - in->y1 + 1;
|
||||
}
|
||||
|
||||
void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
out->a = in->ch.alpha;
|
||||
out->r = in->ch.red;
|
||||
out->g = in->ch.green;
|
||||
out->b = in->ch.blue;
|
||||
#else
|
||||
uint32_t color32 = lv_color_to32(*in);
|
||||
lv_color32_t * color32_t = (lv_color32_t *) &color32;
|
||||
out->a = color32_t->ch.alpha;
|
||||
out->r = color32_t->ch.red;
|
||||
out->g = color32_t->ch.green;
|
||||
out->b = color32_t->ch.blue;
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot)
|
||||
{
|
||||
if(zoom == LV_IMG_ZOOM_NONE) {
|
||||
lv_area_to_sdl_rect(in, out);
|
||||
return;
|
||||
}
|
||||
lv_area_t tmp;
|
||||
_lv_img_buf_get_transformed_area(&tmp, lv_area_get_width(in), lv_area_get_height(in), 0, zoom, pivot);
|
||||
lv_area_move(&tmp, in->x1, in->y1);
|
||||
lv_area_to_sdl_rect(&tmp, out);
|
||||
}
|
||||
|
||||
SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp)
|
||||
{
|
||||
SDL_assert(bpp >= 1 && bpp <= 8);
|
||||
int color_cnt = 1 << bpp;
|
||||
SDL_Palette * result = SDL_AllocPalette(color_cnt);
|
||||
SDL_Color palette[256];
|
||||
for(int i = 0; i < color_cnt; i++) {
|
||||
palette[i].r = palette[i].g = palette[i].b = 0xFF;
|
||||
palette[i].a = mapping ? mapping[i] : i;
|
||||
}
|
||||
SDL_SetPaletteColors(result, palette, 0, color_cnt);
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride)
|
||||
{
|
||||
SDL_Surface * indexed = SDL_CreateRGBSurfaceFrom(opa, width, height, 8, stride, 0, 0, 0, 0);
|
||||
SDL_SetSurfacePalette(indexed, lv_sdl_palette_grayscale8);
|
||||
SDL_Surface * converted = SDL_ConvertSurfaceFormat(indexed, LV_DRAW_SDL_TEXTURE_FORMAT, 0);
|
||||
SDL_FreeSurface(indexed);
|
||||
return converted;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width,
|
||||
lv_coord_t height, lv_coord_t stride)
|
||||
{
|
||||
SDL_Surface * indexed = lv_sdl_create_opa_surface(pixels, width, height, stride);
|
||||
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed);
|
||||
SDL_FreeSurface(indexed);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp)
|
||||
{
|
||||
int src_len = width * height;
|
||||
int cur = 0;
|
||||
int curbit;
|
||||
uint8_t opa_mask;
|
||||
const uint8_t * opa_table;
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
opa_mask = 0x1;
|
||||
opa_table = _lv_bpp1_opa_table;
|
||||
break;
|
||||
case 2:
|
||||
opa_mask = 0x4;
|
||||
opa_table = _lv_bpp2_opa_table;
|
||||
break;
|
||||
case 4:
|
||||
opa_mask = 0xF;
|
||||
opa_table = _lv_bpp4_opa_table;
|
||||
break;
|
||||
case 8:
|
||||
opa_mask = 0xFF;
|
||||
opa_table = _lv_bpp8_opa_table;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
/* Does this work well on big endian systems? */
|
||||
while(cur < src_len) {
|
||||
curbit = 8 - bpp;
|
||||
uint8_t src_byte = src[cur * bpp / 8];
|
||||
while(curbit >= 0 && cur < src_len) {
|
||||
uint8_t src_bits = opa_mask & (src_byte >> curbit);
|
||||
dest[(cur / width * stride) + (cur % width)] = opa_table[src_bits];
|
||||
curbit -= bpp;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
65
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_utils.h
Normal file
65
LVGL.Simulator/lvgl/src/draw/sdl/lv_draw_sdl_utils.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_utils.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_DRAW_SDL_UTILS_H
|
||||
#define LV_DRAW_SDL_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
|
||||
#include LV_GPU_SDL_INCLUDE_PATH
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void _lv_draw_sdl_utils_init();
|
||||
|
||||
void _lv_draw_sdl_utils_deinit();
|
||||
|
||||
void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out);
|
||||
|
||||
void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out);
|
||||
|
||||
void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot);
|
||||
|
||||
SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp);
|
||||
|
||||
SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride);
|
||||
|
||||
SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width,
|
||||
lv_coord_t height, lv_coord_t stride);
|
||||
|
||||
void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SDL_UTILS_H*/
|
||||
@@ -0,0 +1,6 @@
|
||||
CSRCS += lv_gpu_stm32_dma2d.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d"
|
||||
265
LVGL.Simulator/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c
Normal file
265
LVGL.Simulator/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @file lv_gpu_stm32_dma2d.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_gpu_stm32_dma2d.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
|
||||
#include LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_COLOR_16_SWAP
|
||||
// TODO: F7 has red blue swap bit in control register for all layers and output
|
||||
#error "Can't use DMA2D with LV_COLOR_16_SWAP 1"
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
#error "Can't use DMA2D with LV_COLOR_DEPTH == 8"
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
#define LV_DMA2D_COLOR_FORMAT LV_DMA2D_RGB565
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_DMA2D_COLOR_FORMAT LV_DMA2D_ARGB8888
|
||||
#else
|
||||
/*Can't use GPU with other formats*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_draw_stm32_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
||||
lv_color_t color);
|
||||
|
||||
|
||||
static void lv_draw_stm32_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa);
|
||||
|
||||
static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw, const lv_draw_img_dsc_t * dsc,
|
||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
|
||||
|
||||
|
||||
static void invalidate_cache(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Turn on the peripheral and set output color mode, this only needs to be done once
|
||||
*/
|
||||
void lv_draw_stm32_dma2d_init(void)
|
||||
{
|
||||
/*Enable DMA2D clock*/
|
||||
#if defined(STM32F4) || defined(STM32F7)
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
|
||||
#elif defined(STM32H7)
|
||||
RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN;
|
||||
#else
|
||||
# warning "LVGL can't enable the clock of DMA2D"
|
||||
#endif
|
||||
|
||||
/*Wait for hardware access to complete*/
|
||||
__asm volatile("DSB\n");
|
||||
|
||||
/*Delay after setting peripheral clock*/
|
||||
volatile uint32_t temp = RCC->AHB1ENR;
|
||||
LV_UNUSED(temp);
|
||||
|
||||
/*set output colour mode*/
|
||||
DMA2D->OPFCCR = LV_DMA2D_COLOR_FORMAT;
|
||||
}
|
||||
|
||||
|
||||
void lv_draw_stm32_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
|
||||
lv_draw_sw_init_ctx(drv, draw_ctx);
|
||||
|
||||
lv_draw_stm32_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
|
||||
|
||||
dma2d_draw_ctx->blend = lv_draw_stm32_dma2d_blend;
|
||||
// dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_stm32_dma2d_img_decoded;
|
||||
dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_stm32_dma2d_wait_cb;
|
||||
dma2d_draw_ctx->base_draw.buffer_copy = lv_draw_stm32_dma2d_buffer_copy;
|
||||
|
||||
}
|
||||
|
||||
void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
LV_UNUSED(draw_ctx);
|
||||
}
|
||||
|
||||
|
||||
void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||
{
|
||||
lv_area_t blend_area;
|
||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
|
||||
|
||||
bool done = false;
|
||||
|
||||
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
|
||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||
|
||||
lv_color_t * dest_buf = draw_ctx->buf;
|
||||
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
|
||||
|
||||
const lv_color_t * src_buf = dsc->src_buf;
|
||||
if(src_buf) {
|
||||
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||
lv_coord_t src_stride;
|
||||
src_stride = lv_area_get_width(dsc->blend_area);
|
||||
src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1);
|
||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
lv_draw_stm32_dma2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa);
|
||||
done = true;
|
||||
}
|
||||
else if(dsc->opa >= LV_OPA_MAX) {
|
||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
lv_draw_stm32_dma2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||
}
|
||||
|
||||
void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area)
|
||||
{
|
||||
LV_UNUSED(draw_ctx);
|
||||
lv_draw_stm32_dma2d_blend_map(dest_buf, dest_area, dest_stride, src_buf, src_stride, LV_OPA_MAX);
|
||||
}
|
||||
|
||||
|
||||
static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
|
||||
{
|
||||
/*TODO basic ARGB8888 image can be handles here*/
|
||||
|
||||
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
|
||||
}
|
||||
|
||||
static void lv_draw_stm32_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
||||
lv_color_t color)
|
||||
{
|
||||
/*Simply fill an area*/
|
||||
int32_t area_w = lv_area_get_width(fill_area);
|
||||
int32_t area_h = lv_area_get_height(fill_area);
|
||||
invalidate_cache();
|
||||
|
||||
DMA2D->CR = 0x30000;
|
||||
DMA2D->OMAR = (uint32_t)dest_buf;
|
||||
/*as input color mode is same as output we don't need to convert here do we?*/
|
||||
DMA2D->OCOLR = color.full;
|
||||
DMA2D->OOR = dest_stride - area_w;
|
||||
DMA2D->NLR = (area_w << DMA2D_NLR_PL_Pos) | (area_h << DMA2D_NLR_NL_Pos);
|
||||
|
||||
/*start transfer*/
|
||||
DMA2D->CR |= DMA2D_CR_START_Msk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void lv_draw_stm32_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa)
|
||||
{
|
||||
|
||||
/*Simple copy*/
|
||||
int32_t dest_w = lv_area_get_width(dest_area);
|
||||
int32_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
invalidate_cache();
|
||||
if(opa >= LV_OPA_MAX) {
|
||||
DMA2D->CR = 0;
|
||||
/*copy output colour mode, this register controls both input and output colour format*/
|
||||
DMA2D->FGPFCCR = LV_DMA2D_COLOR_FORMAT;
|
||||
DMA2D->FGMAR = (uint32_t)src_buf;
|
||||
DMA2D->FGOR = src_stride - dest_w;
|
||||
DMA2D->OMAR = (uint32_t)dest_buf;
|
||||
DMA2D->OOR = dest_stride - dest_w;
|
||||
DMA2D->NLR = (dest_w << DMA2D_NLR_PL_Pos) | (dest_h << DMA2D_NLR_NL_Pos);
|
||||
|
||||
/*start transfer*/
|
||||
DMA2D->CR |= DMA2D_CR_START_Msk;
|
||||
}
|
||||
else {
|
||||
DMA2D->CR = 0x20000;
|
||||
|
||||
DMA2D->BGPFCCR = LV_DMA2D_COLOR_FORMAT;
|
||||
DMA2D->BGMAR = (uint32_t)dest_buf;
|
||||
DMA2D->BGOR = dest_stride - dest_w;
|
||||
|
||||
DMA2D->FGPFCCR = (uint32_t)LV_DMA2D_COLOR_FORMAT
|
||||
/*alpha mode 2, replace with foreground * alpha value*/
|
||||
| (2 << DMA2D_FGPFCCR_AM_Pos)
|
||||
/*alpha value*/
|
||||
| (opa << DMA2D_FGPFCCR_ALPHA_Pos);
|
||||
DMA2D->FGMAR = (uint32_t)src_buf;
|
||||
DMA2D->FGOR = src_stride - dest_w;
|
||||
|
||||
DMA2D->OMAR = (uint32_t)src_buf;
|
||||
DMA2D->OOR = src_stride - dest_w;
|
||||
DMA2D->NLR = (dest_w << DMA2D_NLR_PL_Pos) | (dest_h << DMA2D_NLR_NL_Pos);
|
||||
|
||||
/*start transfer*/
|
||||
DMA2D->CR |= DMA2D_CR_START_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
if(disp->driver && disp->driver->wait_cb) {
|
||||
while(DMA2D->CR & DMA2D_CR_START_Msk) {
|
||||
disp->driver->wait_cb(disp->driver);
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(DMA2D->CR & DMA2D_CR_START_Msk);
|
||||
}
|
||||
lv_draw_sw_wait_for_finish(draw_ctx);
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void invalidate_cache(void)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver);
|
||||
else {
|
||||
#if __CORTEX_M >= 0x07
|
||||
if((SCB->CCR) & (uint32_t)SCB_CCR_DC_Msk)
|
||||
SCB_CleanInvalidateDCache();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file lv_gpu_stm32_dma2d.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GPU_STM32_DMA2D_H
|
||||
#define LV_GPU_STM32_DMA2D_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../hal/lv_hal_disp.h"
|
||||
#include "../sw/lv_draw_sw.h"
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_DMA2D_ARGB8888 0
|
||||
#define LV_DMA2D_RGB888 1
|
||||
#define LV_DMA2D_RGB565 2
|
||||
#define LV_DMA2D_ARGB1555 3
|
||||
#define LV_DMA2D_ARGB4444 4
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef lv_draw_sw_ctx_t lv_draw_stm32_dma2d_ctx_t;
|
||||
|
||||
struct _lv_disp_drv_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Turn on the peripheral and set output color mode, this only needs to be done once
|
||||
*/
|
||||
void lv_draw_stm32_dma2d_init(void);
|
||||
|
||||
void lv_draw_stm32_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_stm32_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
|
||||
void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
|
||||
void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_STM32_DMA2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GPU_STM32_DMA2D_H*/
|
||||
101
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.c
Normal file
101
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file lv_draw_sw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_draw.h"
|
||||
#include "lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sw_init_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
|
||||
lv_draw_sw_ctx_t * draw_sw_ctx = (lv_draw_sw_ctx_t *) draw_ctx;
|
||||
lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t));
|
||||
|
||||
draw_sw_ctx->base_draw.draw_arc = lv_draw_sw_arc;
|
||||
draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect;
|
||||
draw_sw_ctx->base_draw.draw_bg = lv_draw_sw_bg;
|
||||
draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter;
|
||||
draw_sw_ctx->base_draw.draw_img_decoded = lv_draw_sw_img_decoded;
|
||||
draw_sw_ctx->base_draw.draw_line = lv_draw_sw_line;
|
||||
draw_sw_ctx->base_draw.draw_polygon = lv_draw_sw_polygon;
|
||||
draw_sw_ctx->base_draw.wait_for_finish = lv_draw_sw_wait_for_finish;
|
||||
draw_sw_ctx->base_draw.buffer_copy = lv_draw_sw_buffer_copy;
|
||||
draw_sw_ctx->blend = lv_draw_sw_blend_basic;
|
||||
}
|
||||
|
||||
void lv_draw_sw_deinit_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
LV_UNUSED(drv);
|
||||
|
||||
lv_draw_sw_ctx_t * draw_sw_ctx = (lv_draw_sw_ctx_t *) draw_ctx;
|
||||
lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t));
|
||||
}
|
||||
|
||||
void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
LV_UNUSED(draw_ctx);
|
||||
/*Nothing to wait for*/
|
||||
}
|
||||
|
||||
void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area)
|
||||
{
|
||||
LV_UNUSED(draw_ctx);
|
||||
|
||||
lv_color_t * dest_bufc = dest_buf;
|
||||
lv_color_t * src_bufc = src_buf;
|
||||
|
||||
/*Got the first pixel of each buffer*/
|
||||
dest_bufc += dest_stride * dest_area->y1;
|
||||
dest_bufc += dest_area->x1;
|
||||
|
||||
src_bufc += src_stride * src_area->y1;
|
||||
src_bufc += src_area->x1;
|
||||
|
||||
uint32_t line_length = lv_area_get_width(dest_area) * sizeof(lv_color_t);
|
||||
lv_coord_t y;
|
||||
for(y = dest_area->y1; y <= dest_area->y2; y++) {
|
||||
lv_memcpy(dest_bufc, src_bufc, line_length);
|
||||
dest_bufc += dest_stride;
|
||||
src_bufc += src_stride;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
81
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.h
Normal file
81
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @file lv_draw_sw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SW_H
|
||||
#define LV_DRAW_SW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sw_blend.h"
|
||||
#include "../lv_draw.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../hal/lv_hal_disp.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_disp_drv_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_ctx_t base_draw;
|
||||
|
||||
/** Fill an area of the destination buffer with a color*/
|
||||
void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
} lv_draw_sw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_sw_init_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
void lv_draw_sw_deinit_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius,
|
||||
uint16_t start_angle, uint16_t end_angle);
|
||||
|
||||
void lv_draw_sw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
|
||||
void lv_draw_sw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||
void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
|
||||
uint32_t letter);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc,
|
||||
const lv_point_t * point1, const lv_point_t * point2);
|
||||
|
||||
void lv_draw_sw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc,
|
||||
const lv_point_t * points, uint16_t point_cnt);
|
||||
|
||||
void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SW_H*/
|
||||
15
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.mk
Normal file
15
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw.mk
Normal file
@@ -0,0 +1,15 @@
|
||||
CSRCS += lv_draw_sw.c
|
||||
CSRCS += lv_draw_sw_arc.c
|
||||
CSRCS += lv_draw_sw_blend.c
|
||||
CSRCS += lv_draw_sw_img.c
|
||||
CSRCS += lv_draw_sw_letter.c
|
||||
CSRCS += lv_draw_sw_line.c
|
||||
CSRCS += lv_draw_sw_rect.c
|
||||
CSRCS += lv_draw_sw_polygon.c
|
||||
CSRCS += lv_draw_sw_gradient.c
|
||||
CSRCS += lv_draw_sw_dither.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw"
|
||||
531
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_arc.c
Normal file
531
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_arc.c
Normal file
@@ -0,0 +1,531 @@
|
||||
/**
|
||||
* @file lv_draw_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sw.h"
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../misc/lv_log.h"
|
||||
#include "../../misc/lv_mem.h"
|
||||
#include "../lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define SPLIT_RADIUS_LIMIT 10 /*With radius greater than this the arc will drawn in quarters. A quarter is drawn only if there is arc in it*/
|
||||
#define SPLIT_ANGLE_GAP_LIMIT 60 /*With small gaps in the arc don't bother with splitting because there is nothing to skip.*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
const lv_point_t * center;
|
||||
lv_coord_t radius;
|
||||
uint16_t start_angle;
|
||||
uint16_t end_angle;
|
||||
uint16_t start_quarter;
|
||||
uint16_t end_quarter;
|
||||
lv_coord_t width;
|
||||
lv_draw_rect_dsc_t * draw_dsc;
|
||||
const lv_area_t * draw_area;
|
||||
lv_draw_ctx_t * draw_ctx;
|
||||
} quarter_draw_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void draw_quarter_0(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_1(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_2(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_3(quarter_draw_dsc_t * q);
|
||||
static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius,
|
||||
uint16_t start_angle, uint16_t end_angle)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->width == 0) return;
|
||||
if(start_angle == end_angle) return;
|
||||
|
||||
lv_coord_t width = dsc->width;
|
||||
if(width > radius) width = radius;
|
||||
|
||||
lv_draw_rect_dsc_t cir_dsc;
|
||||
lv_draw_rect_dsc_init(&cir_dsc);
|
||||
cir_dsc.blend_mode = dsc->blend_mode;
|
||||
if(dsc->img_src) {
|
||||
cir_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
cir_dsc.bg_img_src = dsc->img_src;
|
||||
cir_dsc.bg_img_opa = dsc->opa;
|
||||
}
|
||||
else {
|
||||
cir_dsc.bg_opa = dsc->opa;
|
||||
cir_dsc.bg_color = dsc->color;
|
||||
}
|
||||
|
||||
lv_area_t area_out;
|
||||
area_out.x1 = center->x - radius;
|
||||
area_out.y1 = center->y - radius;
|
||||
area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/
|
||||
area_out.y2 = center->y + radius - 1;
|
||||
|
||||
lv_area_t area_in;
|
||||
lv_area_copy(&area_in, &area_out);
|
||||
area_in.x1 += dsc->width;
|
||||
area_in.y1 += dsc->width;
|
||||
area_in.x2 -= dsc->width;
|
||||
area_in.y2 -= dsc->width;
|
||||
|
||||
/*Create inner the mask*/
|
||||
int16_t mask_in_id = LV_MASK_ID_INV;
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
|
||||
lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
|
||||
mask_in_id = lv_draw_mask_add(&mask_in_param, NULL);
|
||||
}
|
||||
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL);
|
||||
|
||||
/*Draw a full ring*/
|
||||
if(start_angle + 360 == end_angle || start_angle == end_angle + 360) {
|
||||
cir_dsc.radius = LV_RADIUS_CIRCLE;
|
||||
lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
|
||||
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
|
||||
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while(start_angle >= 360) start_angle -= 360;
|
||||
while(end_angle >= 360) end_angle -= 360;
|
||||
|
||||
lv_draw_mask_angle_param_t mask_angle_param;
|
||||
lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
|
||||
int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL);
|
||||
|
||||
int32_t angle_gap;
|
||||
if(end_angle > start_angle) {
|
||||
angle_gap = 360 - (end_angle - start_angle);
|
||||
}
|
||||
else {
|
||||
angle_gap = start_angle - end_angle;
|
||||
}
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
|
||||
if(angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) {
|
||||
/*Handle each quarter individually and skip which is empty*/
|
||||
quarter_draw_dsc_t q_dsc;
|
||||
q_dsc.center = center;
|
||||
q_dsc.radius = radius;
|
||||
q_dsc.start_angle = start_angle;
|
||||
q_dsc.end_angle = end_angle;
|
||||
q_dsc.start_quarter = (start_angle / 90) & 0x3;
|
||||
q_dsc.end_quarter = (end_angle / 90) & 0x3;
|
||||
q_dsc.width = width;
|
||||
q_dsc.draw_dsc = &cir_dsc;
|
||||
q_dsc.draw_area = &area_out;
|
||||
q_dsc.draw_ctx = draw_ctx;
|
||||
|
||||
draw_quarter_0(&q_dsc);
|
||||
draw_quarter_1(&q_dsc);
|
||||
draw_quarter_2(&q_dsc);
|
||||
draw_quarter_3(&q_dsc);
|
||||
}
|
||||
else {
|
||||
lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
|
||||
}
|
||||
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
|
||||
lv_draw_mask_remove_id(mask_angle_id);
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
|
||||
|
||||
if(dsc->rounded) {
|
||||
|
||||
lv_draw_mask_radius_param_t mask_end_param;
|
||||
|
||||
lv_area_t round_area;
|
||||
get_rounded_area(start_angle, radius, width, &round_area);
|
||||
round_area.x1 += center->x;
|
||||
round_area.x2 += center->x;
|
||||
round_area.y1 += center->y;
|
||||
round_area.y2 += center->y;
|
||||
lv_area_t clip_area2;
|
||||
if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
|
||||
lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
|
||||
|
||||
draw_ctx->clip_area = &clip_area2;
|
||||
lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
|
||||
get_rounded_area(end_angle, radius, width, &round_area);
|
||||
round_area.x1 += center->x;
|
||||
round_area.x2 += center->x;
|
||||
round_area.y1 += center->y;
|
||||
round_area.y2 += center->y;
|
||||
if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
|
||||
lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
|
||||
|
||||
draw_ctx->clip_area = &clip_area2;
|
||||
lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
#else
|
||||
LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0");
|
||||
LV_UNUSED(center);
|
||||
LV_UNUSED(radius);
|
||||
LV_UNUSED(start_angle);
|
||||
LV_UNUSED(end_angle);
|
||||
LV_UNUSED(draw_ctx);
|
||||
LV_UNUSED(dsc);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void draw_quarter_0(quarter_draw_dsc_t * q)
|
||||
{
|
||||
const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
else if(q->start_quarter == 0 || q->end_quarter == 0) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 0) {
|
||||
quarter_area.x1 = q->center->x;
|
||||
quarter_area.y2 = q->center->y + q->radius;
|
||||
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
if(q->end_quarter == 0) {
|
||||
quarter_area.x2 = q->center->x + q->radius;
|
||||
quarter_area.y1 = q->center->y;
|
||||
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 1) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 2) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 1)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center->x;
|
||||
quarter_area.y1 = q->center->y;
|
||||
quarter_area.x2 = q->center->x + q->radius;
|
||||
quarter_area.y2 = q->center->y + q->radius;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
q->draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
static void draw_quarter_1(quarter_draw_dsc_t * q)
|
||||
{
|
||||
const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
else if(q->start_quarter == 1 || q->end_quarter == 1) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 1) {
|
||||
quarter_area.x1 = q->center->x - q->radius;
|
||||
quarter_area.y1 = q->center->y;
|
||||
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
if(q->end_quarter == 1) {
|
||||
quarter_area.x2 = q->center->x - 1;
|
||||
quarter_area.y2 = q->center->y + q->radius;
|
||||
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 2) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 2)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center->x - q->radius;
|
||||
quarter_area.y1 = q->center->y;
|
||||
quarter_area.x2 = q->center->x - 1;
|
||||
quarter_area.y2 = q->center->y + q->radius;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
q->draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
static void draw_quarter_2(quarter_draw_dsc_t * q)
|
||||
{
|
||||
const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
else if(q->start_quarter == 2 || q->end_quarter == 2) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 2) {
|
||||
quarter_area.x2 = q->center->x - 1;
|
||||
quarter_area.y1 = q->center->y - q->radius;
|
||||
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
if(q->end_quarter == 2) {
|
||||
quarter_area.x1 = q->center->x - q->radius;
|
||||
quarter_area.y2 = q->center->y - 1;
|
||||
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 0)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center->x - q->radius;
|
||||
quarter_area.y1 = q->center->y - q->radius;
|
||||
quarter_area.x2 = q->center->x - 1;
|
||||
quarter_area.y2 = q->center->y - 1;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
q->draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
static void draw_quarter_3(quarter_draw_dsc_t * q)
|
||||
{
|
||||
const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
else if(q->start_quarter == 3 || q->end_quarter == 3) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 3) {
|
||||
quarter_area.x2 = q->center->x + q->radius;
|
||||
quarter_area.y2 = q->center->y - 1;
|
||||
|
||||
quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
if(q->end_quarter == 3) {
|
||||
quarter_area.x1 = q->center->x;
|
||||
quarter_area.y1 = q->center->y - q->radius;
|
||||
|
||||
quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 0) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 0) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 1)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center->x;
|
||||
quarter_area.y1 = q->center->y - q->radius;
|
||||
quarter_area.x2 = q->center->x + q->radius;
|
||||
quarter_area.y2 = q->center->y - 1;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
|
||||
if(ok) {
|
||||
q->draw_ctx->clip_area = &quarter_area;
|
||||
lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
|
||||
}
|
||||
}
|
||||
|
||||
q->draw_ctx->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area)
|
||||
{
|
||||
const uint8_t ps = 8;
|
||||
const uint8_t pa = 127;
|
||||
|
||||
int32_t thick_half = thickness / 2;
|
||||
uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
|
||||
|
||||
int32_t cir_x;
|
||||
int32_t cir_y;
|
||||
|
||||
cir_x = ((radius - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
|
||||
/*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
|
||||
if(cir_x > 0) {
|
||||
cir_x = (cir_x - pa) >> ps;
|
||||
res_area->x1 = cir_x - thick_half + thick_corr;
|
||||
res_area->x2 = cir_x + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_x = (cir_x + pa) >> ps;
|
||||
res_area->x1 = cir_x - thick_half;
|
||||
res_area->x2 = cir_x + thick_half - thick_corr;
|
||||
}
|
||||
|
||||
if(cir_y > 0) {
|
||||
cir_y = (cir_y - pa) >> ps;
|
||||
res_area->y1 = cir_y - thick_half + thick_corr;
|
||||
res_area->y2 = cir_y + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_y = (cir_y + pa) >> ps;
|
||||
res_area->y1 = cir_y - thick_half;
|
||||
res_area->y2 = cir_y + thick_half - thick_corr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
757
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_blend.c
Normal file
757
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_blend.c
Normal file
@@ -0,0 +1,757 @@
|
||||
/**
|
||||
* @file lv_draw_sw_blend.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sw.h"
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../hal/lv_hal_disp.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_coord_t dest_stride,
|
||||
lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stide);
|
||||
LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride);
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color,
|
||||
lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
static void map_set_px(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa,
|
||||
const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode);
|
||||
|
||||
static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa);
|
||||
static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa);
|
||||
static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_COLOR_SCREEN_TRANSP == 0
|
||||
#define FILL_NORMAL_MASK_PX(color) \
|
||||
if(*mask == LV_OPA_COVER) *dest_buf = color; \
|
||||
else *dest_buf = lv_color_mix(color, *dest_buf, *mask); \
|
||||
mask++; \
|
||||
dest_buf++;
|
||||
|
||||
#else
|
||||
#define FILL_NORMAL_MASK_PX(color) \
|
||||
if(*mask == LV_OPA_COVER) *dest_buf = color; \
|
||||
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(*dest_buf, dest_buf->ch.alpha, color, *mask, dest_buf, &dest_buf->ch.alpha); \
|
||||
else *dest_buf = lv_color_mix(color, *dest_buf, *mask); \
|
||||
mask++; \
|
||||
dest_buf++;
|
||||
#endif
|
||||
|
||||
#define MAP_NORMAL_MASK_PX(x) \
|
||||
if(*mask_tmp_x) { \
|
||||
if(*mask_tmp_x == LV_OPA_COVER) dest_buf[x] = src_buf[x]; \
|
||||
else dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], *mask_tmp_x); \
|
||||
} \
|
||||
mask_tmp_x++;
|
||||
|
||||
#define MAP_NORMAL_MASK_PX_SCR_TRANSP(x) \
|
||||
if(*mask_tmp_x) { \
|
||||
if(*mask_tmp_x == LV_OPA_COVER) dest_buf[x] = src_buf[x]; \
|
||||
else if(disp->driver->screen_transp) lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, \
|
||||
src_buf[x], *mask_tmp_x, &dest_buf[x], &dest_buf[x].ch.alpha); \
|
||||
else dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], *mask_tmp_x); \
|
||||
} \
|
||||
mask_tmp_x++;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_sw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||
{
|
||||
/*Do not draw transparent things*/
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_area_t blend_area;
|
||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
|
||||
|
||||
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
|
||||
|
||||
((lv_draw_sw_ctx_t *)draw_ctx)->blend(draw_ctx, dsc);
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||
{
|
||||
const lv_opa_t * mask;
|
||||
if(dsc->mask_buf == NULL) mask = NULL;
|
||||
if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return;
|
||||
else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL;
|
||||
else mask = dsc->mask_buf;
|
||||
|
||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||
|
||||
lv_area_t blend_area;
|
||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
|
||||
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_color_t * dest_buf = draw_ctx->buf;
|
||||
if(disp->driver->set_px_cb == NULL) {
|
||||
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
|
||||
}
|
||||
|
||||
const lv_color_t * src_buf = dsc->src_buf;
|
||||
lv_coord_t src_stride;
|
||||
if(src_buf) {
|
||||
src_stride = lv_area_get_width(dsc->blend_area);
|
||||
src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1);
|
||||
}
|
||||
else {
|
||||
src_stride = 0;
|
||||
}
|
||||
|
||||
lv_coord_t mask_stride;
|
||||
if(mask) {
|
||||
mask_stride = lv_area_get_width(dsc->mask_area);
|
||||
mask += mask_stride * (dsc->mask_area->y1 - blend_area.y1) + (dsc->mask_area->x1 - blend_area.x1);
|
||||
}
|
||||
else {
|
||||
mask_stride = 0;
|
||||
}
|
||||
|
||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||
|
||||
|
||||
if(disp->driver->set_px_cb) {
|
||||
if(dsc->src_buf == NULL) {
|
||||
fill_set_px(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride);
|
||||
}
|
||||
else {
|
||||
map_set_px(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride);
|
||||
}
|
||||
}
|
||||
else if(dsc->src_buf == NULL) {
|
||||
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
|
||||
fill_normal(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
else {
|
||||
fill_blended(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride, dsc->blend_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
|
||||
map_normal(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
else {
|
||||
map_blended(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride, dsc->blend_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_coord_t dest_stride,
|
||||
lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stide)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
if(mask == NULL) {
|
||||
for(y = blend_area->y1; y <= blend_area->y2; y++) {
|
||||
for(x = blend_area->x1; x <= blend_area->x2; x++) {
|
||||
disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, x, y, color, opa);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int32_t w = lv_area_get_width(blend_area);
|
||||
int32_t h = lv_area_get_height(blend_area);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(mask[x]) {
|
||||
disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, blend_area->x1 + x, blend_area->y1 + y, color,
|
||||
(uint32_t)((uint32_t)opa * mask[x]) >> 8);
|
||||
}
|
||||
}
|
||||
mask += mask_stide;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride)
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
int32_t w = lv_area_get_width(dest_area);
|
||||
int32_t h = lv_area_get_height(dest_area);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
/*No mask*/
|
||||
if(mask == NULL) {
|
||||
if(opa >= LV_OPA_MAX) {
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_color_fill(dest_buf, color, w);
|
||||
dest_buf += dest_stride;
|
||||
}
|
||||
}
|
||||
/*Has opacity*/
|
||||
else {
|
||||
lv_color_t last_dest_color = lv_color_black();
|
||||
lv_color_t last_res_color = lv_color_mix(color, last_dest_color, opa);
|
||||
|
||||
uint16_t color_premult[3];
|
||||
lv_color_premult(color, opa, color_premult);
|
||||
lv_opa_t opa_inv = 255 - opa;
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(last_dest_color.full != dest_buf[x].full) {
|
||||
last_dest_color = dest_buf[x];
|
||||
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp->driver->screen_transp) {
|
||||
lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, color, opa, &last_res_color,
|
||||
&last_res_color.ch.alpha);
|
||||
}
|
||||
else
|
||||
#else
|
||||
LV_UNUSED(disp);
|
||||
#endif
|
||||
{
|
||||
last_res_color = lv_color_mix_premult(color_premult, dest_buf[x], opa_inv);
|
||||
}
|
||||
}
|
||||
dest_buf[x] = last_res_color;
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Masked*/
|
||||
else {
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
uint32_t c32 = color.full + ((uint32_t)color.full << 16);
|
||||
#endif
|
||||
/*Only the mask matters*/
|
||||
if(opa >= LV_OPA_MAX) {
|
||||
int32_t x_end4 = w - 4;
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w && ((lv_uintptr_t)(mask) & 0x3); x++) {
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
}
|
||||
|
||||
for(; x <= x_end4; x += 4) {
|
||||
uint32_t mask32 = *((uint32_t *)mask);
|
||||
if(mask32 == 0xFFFFFFFF) {
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
if((lv_uintptr_t)dest_buf & 0x3) {
|
||||
*(dest_buf + 0) = color;
|
||||
uint32_t * d = (uint32_t *)(dest_buf + 1);
|
||||
*d = c32;
|
||||
*(dest_buf + 3) = color;
|
||||
}
|
||||
else {
|
||||
uint32_t * d = (uint32_t *)dest_buf;
|
||||
*d = c32;
|
||||
*(d + 1) = c32;
|
||||
}
|
||||
#else
|
||||
dest_buf[0] = color;
|
||||
dest_buf[1] = color;
|
||||
dest_buf[2] = color;
|
||||
dest_buf[3] = color;
|
||||
#endif
|
||||
dest_buf += 4;
|
||||
mask += 4;
|
||||
}
|
||||
else if(mask32) {
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
}
|
||||
else {
|
||||
mask += 4;
|
||||
dest_buf += 4;
|
||||
}
|
||||
}
|
||||
|
||||
for(; x < w ; x++) {
|
||||
FILL_NORMAL_MASK_PX(color)
|
||||
}
|
||||
dest_buf += (dest_stride - w);
|
||||
mask += (mask_stride - w);
|
||||
}
|
||||
}
|
||||
/*With opacity*/
|
||||
else {
|
||||
/*Buffer the result color to avoid recalculating the same color*/
|
||||
lv_color_t last_dest_color;
|
||||
lv_color_t last_res_color;
|
||||
lv_opa_t last_mask = LV_OPA_TRANSP;
|
||||
last_dest_color.full = dest_buf[0].full;
|
||||
last_res_color.full = dest_buf[0].full;
|
||||
lv_opa_t opa_tmp = LV_OPA_TRANSP;
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(*mask) {
|
||||
if(*mask != last_mask) opa_tmp = *mask == LV_OPA_COVER ? opa :
|
||||
(uint32_t)((uint32_t)(*mask) * opa) >> 8;
|
||||
if(*mask != last_mask || last_dest_color.full != dest_buf[x].full) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp->driver->screen_transp) {
|
||||
lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, color, opa_tmp, &last_res_color,
|
||||
&last_res_color.ch.alpha);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(opa_tmp == LV_OPA_COVER) last_res_color = color;
|
||||
else last_res_color = lv_color_mix(color, dest_buf[x], opa_tmp);
|
||||
}
|
||||
last_mask = *mask;
|
||||
last_dest_color.full = dest_buf[x].full;
|
||||
}
|
||||
dest_buf[x] = last_res_color;
|
||||
}
|
||||
mask++;
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
mask += (mask_stride - w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
||||
lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride,
|
||||
lv_blend_mode_t blend_mode)
|
||||
{
|
||||
|
||||
int32_t w = lv_area_get_width(dest_area);
|
||||
int32_t h = lv_area_get_height(dest_area);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
blend_fp = color_blend_true_color_additive;
|
||||
break;
|
||||
case LV_BLEND_MODE_SUBTRACTIVE:
|
||||
blend_fp = color_blend_true_color_subtractive;
|
||||
break;
|
||||
case LV_BLEND_MODE_MULTIPLY:
|
||||
blend_fp = color_blend_true_color_multiply;
|
||||
break;
|
||||
default:
|
||||
LV_LOG_WARN("fill_blended: unsupported blend mode");
|
||||
return;
|
||||
}
|
||||
|
||||
/*Simple fill (maybe with opacity), no masking*/
|
||||
if(mask == NULL) {
|
||||
lv_color_t last_dest_color = dest_buf[0];
|
||||
lv_color_t last_res_color = blend_fp(color, dest_buf[0], opa);
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(last_dest_color.full != dest_buf[x].full) {
|
||||
last_dest_color = dest_buf[x];
|
||||
last_res_color = blend_fp(color, dest_buf[x], opa);
|
||||
}
|
||||
dest_buf[x] = last_res_color;
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
}
|
||||
}
|
||||
/*Masked*/
|
||||
else {
|
||||
/*Buffer the result color to avoid recalculating the same color*/
|
||||
lv_color_t last_dest_color;
|
||||
lv_color_t last_res_color;
|
||||
lv_opa_t last_mask = LV_OPA_TRANSP;
|
||||
last_dest_color = dest_buf[0];
|
||||
lv_opa_t opa_tmp = mask[0] >= LV_OPA_MAX ? opa : (uint32_t)((uint32_t)mask[0] * opa) >> 8;
|
||||
last_res_color = blend_fp(color, last_dest_color, opa_tmp);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(mask[x] == 0) continue;
|
||||
if(mask[x] != last_mask || last_dest_color.full != dest_buf[x].full) {
|
||||
opa_tmp = mask[x] >= LV_OPA_MAX ? opa : (uint32_t)((uint32_t)mask[x] * opa) >> 8;
|
||||
|
||||
last_res_color = blend_fp(color, dest_buf[x], opa_tmp);
|
||||
last_mask = mask[x];
|
||||
last_dest_color.full = dest_buf[x].full;
|
||||
}
|
||||
dest_buf[x] = last_res_color;
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
mask += mask_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void map_set_px(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride)
|
||||
|
||||
{
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
|
||||
int32_t w = lv_area_get_width(dest_area);
|
||||
int32_t h = lv_area_get_height(dest_area);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
if(mask == NULL) {
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, dest_area->x1 + x, dest_area->y1 + y, src_buf[x],
|
||||
opa);
|
||||
}
|
||||
src_buf += src_stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(mask[x]) {
|
||||
disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, dest_area->x1 + x, dest_area->y1 + y, src_buf[x],
|
||||
(uint32_t)((uint32_t)opa * mask[x]) >> 8);
|
||||
}
|
||||
}
|
||||
mask += mask_stride;
|
||||
src_buf += src_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void map_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride)
|
||||
|
||||
{
|
||||
int32_t w = lv_area_get_width(dest_area);
|
||||
int32_t h = lv_area_get_height(dest_area);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
#endif
|
||||
|
||||
/*Simple fill (maybe with opacity), no masking*/
|
||||
if(mask == NULL) {
|
||||
if(opa >= LV_OPA_MAX) {
|
||||
for(y = 0; y < h; y++) {
|
||||
lv_memcpy(dest_buf, src_buf, w * sizeof(lv_color_t));
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp->driver->screen_transp) {
|
||||
lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, src_buf[x], opa, &dest_buf[x],
|
||||
&dest_buf[x].ch.alpha);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa);
|
||||
}
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Masked*/
|
||||
else {
|
||||
/*Only the mask matters*/
|
||||
if(opa > LV_OPA_MAX) {
|
||||
int32_t x_end4 = w - 4;
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
const lv_opa_t * mask_tmp_x = mask;
|
||||
#if 0
|
||||
for(x = 0; x < w; x++) {
|
||||
MAP_NORMAL_MASK_PX(x);
|
||||
}
|
||||
#else
|
||||
for(x = 0; x < w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x)
|
||||
#else
|
||||
MAP_NORMAL_MASK_PX(x)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t * mask32 = (uint32_t *)mask_tmp_x;
|
||||
for(; x < x_end4; x += 4) {
|
||||
if(*mask32) {
|
||||
if((*mask32) == 0xFFFFFFFF) {
|
||||
dest_buf[x] = src_buf[x];
|
||||
dest_buf[x + 1] = src_buf[x + 1];
|
||||
dest_buf[x + 2] = src_buf[x + 2];
|
||||
dest_buf[x + 3] = src_buf[x + 3];
|
||||
}
|
||||
else {
|
||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x)
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 1)
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 2)
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x + 3)
|
||||
#else
|
||||
MAP_NORMAL_MASK_PX(x)
|
||||
MAP_NORMAL_MASK_PX(x + 1)
|
||||
MAP_NORMAL_MASK_PX(x + 2)
|
||||
MAP_NORMAL_MASK_PX(x + 3)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
mask32++;
|
||||
}
|
||||
|
||||
mask_tmp_x = (const lv_opa_t *)mask32;
|
||||
for(; x < w ; x++) {
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
MAP_NORMAL_MASK_PX_SCR_TRANSP(x)
|
||||
#else
|
||||
MAP_NORMAL_MASK_PX(x)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
mask += mask_stride;
|
||||
}
|
||||
}
|
||||
/*Handle opa and mask values too*/
|
||||
else {
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(mask[x]) {
|
||||
lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8);
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp->driver->screen_transp) {
|
||||
lv_color_mix_with_alpha(dest_buf[x], dest_buf[x].ch.alpha, src_buf[x], opa_tmp,
|
||||
&dest_buf[x], &dest_buf[x].ch.alpha);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa_tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
mask += mask_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa,
|
||||
const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
|
||||
int32_t w = lv_area_get_width(dest_area);
|
||||
int32_t h = lv_area_get_height(dest_area);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
||||
lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
blend_fp = color_blend_true_color_additive;
|
||||
break;
|
||||
case LV_BLEND_MODE_SUBTRACTIVE:
|
||||
blend_fp = color_blend_true_color_subtractive;
|
||||
break;
|
||||
case LV_BLEND_MODE_MULTIPLY:
|
||||
blend_fp = color_blend_true_color_multiply;
|
||||
break;
|
||||
default:
|
||||
LV_LOG_WARN("fill_blended: unsupported blend mode");
|
||||
return;
|
||||
}
|
||||
|
||||
/*Simple fill (maybe with opacity), no masking*/
|
||||
if(mask == NULL) {
|
||||
/*The map will be indexed from `draw_area->x1` so compensate it.*/
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
dest_buf[x] = blend_fp(src_buf[x], dest_buf[x], opa);
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
}
|
||||
}
|
||||
/*Masked*/
|
||||
else {
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
if(mask[x] == 0) continue;
|
||||
lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8);
|
||||
dest_buf[x] = blend_fp(src_buf[x], dest_buf[x], opa_tmp);
|
||||
}
|
||||
dest_buf += dest_stride;
|
||||
src_buf += src_stride;
|
||||
mask += mask_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
||||
{
|
||||
|
||||
if(opa <= LV_OPA_MIN) return bg;
|
||||
|
||||
uint32_t tmp;
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
tmp = bg.full + fg.full;
|
||||
fg.full = LV_MIN(tmp, 1);
|
||||
#else
|
||||
tmp = bg.ch.red + fg.ch.red;
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
fg.ch.red = LV_MIN(tmp, 7);
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
fg.ch.red = LV_MIN(tmp, 31);
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
fg.ch.red = LV_MIN(tmp, 255);
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
tmp = bg.ch.green + fg.ch.green;
|
||||
fg.ch.green = LV_MIN(tmp, 7);
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
tmp = bg.ch.green + fg.ch.green;
|
||||
fg.ch.green = LV_MIN(tmp, 63);
|
||||
#else
|
||||
tmp = (bg.ch.green_h << 3) + bg.ch.green_l + (fg.ch.green_h << 3) + fg.ch.green_l;
|
||||
tmp = LV_MIN(tmp, 63);
|
||||
fg.ch.green_h = tmp >> 3;
|
||||
fg.ch.green_l = tmp & 0x7;
|
||||
#endif
|
||||
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
tmp = bg.ch.green + fg.ch.green;
|
||||
fg.ch.green = LV_MIN(tmp, 255);
|
||||
#endif
|
||||
|
||||
tmp = bg.ch.blue + fg.ch.blue;
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
fg.ch.blue = LV_MIN(tmp, 4);
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
fg.ch.blue = LV_MIN(tmp, 31);
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
fg.ch.blue = LV_MIN(tmp, 255);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(opa == LV_OPA_COVER) return fg;
|
||||
|
||||
return lv_color_mix(fg, bg, opa);
|
||||
}
|
||||
|
||||
static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
||||
{
|
||||
if(opa <= LV_OPA_MIN) return bg;
|
||||
|
||||
int32_t tmp;
|
||||
tmp = bg.ch.red - fg.ch.red;
|
||||
fg.ch.red = LV_MAX(tmp, 0);
|
||||
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
tmp = bg.ch.green - fg.ch.green;
|
||||
fg.ch.green = LV_MAX(tmp, 0);
|
||||
#else
|
||||
tmp = (bg.ch.green_h << 3) + bg.ch.green_l + (fg.ch.green_h << 3) + fg.ch.green_l;
|
||||
tmp = LV_MAX(tmp, 0);
|
||||
fg.ch.green_h = tmp >> 3;
|
||||
fg.ch.green_l = tmp & 0x7;
|
||||
#endif
|
||||
|
||||
tmp = bg.ch.blue - fg.ch.blue;
|
||||
fg.ch.blue = LV_MAX(tmp, 0);
|
||||
|
||||
if(opa == LV_OPA_COVER) return fg;
|
||||
|
||||
return lv_color_mix(fg, bg, opa);
|
||||
}
|
||||
|
||||
static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa)
|
||||
{
|
||||
if(opa <= LV_OPA_MIN) return bg;
|
||||
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
fg.ch.red = (fg.ch.red * bg.ch.red) >> 8;
|
||||
fg.ch.green = (fg.ch.green * bg.ch.green) >> 8;
|
||||
fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 8;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
fg.ch.red = (fg.ch.red * bg.ch.red) >> 5;
|
||||
fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 5;
|
||||
LV_COLOR_SET_G(fg, (LV_COLOR_GET_G(fg) * LV_COLOR_GET_G(bg)) >> 6);
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
fg.ch.red = (fg.ch.red * bg.ch.red) >> 3;
|
||||
fg.ch.green = (fg.ch.green * bg.ch.green) >> 3;
|
||||
fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 2;
|
||||
#endif
|
||||
|
||||
if(opa == LV_OPA_COVER) return fg;
|
||||
|
||||
return lv_color_mix(fg, bg, opa);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
69
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_blend.h
Normal file
69
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_blend.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file lv_draw_sw_blend.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SW_BLEND_H
|
||||
#define LV_DRAW_SW_BLEND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../misc/lv_color.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../misc/lv_style.h"
|
||||
#include "../lv_draw_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
const lv_area_t * blend_area; /**< The area with absolute coordinates to draw on `draw_ctx->buf`
|
||||
* will be clipped to `draw_ctx->clip_area` */
|
||||
const lv_color_t * src_buf; /**< Pointer to an image to blend. If set `fill_color` is ignored */
|
||||
lv_color_t color; /**< Fill color*/
|
||||
lv_opa_t * mask_buf; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/
|
||||
lv_draw_mask_res_t mask_res; /**< The result of the previous mask operation */
|
||||
const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/
|
||||
lv_opa_t opa; /**< The overall opacity*/
|
||||
lv_blend_mode_t blend_mode; /**< E.g. LV_BLEND_MODE_ADDITIVE*/
|
||||
} lv_draw_sw_blend_dsc_t;
|
||||
|
||||
struct _lv_draw_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Call the blend function of the `draw_ctx`.
|
||||
* @param draw_ctx pointer to a draw context
|
||||
* @param dsc pointer to an initialized blend descriptor
|
||||
*/
|
||||
void lv_draw_sw_blend(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* The basic blend function used with software rendering.
|
||||
* @param draw_ctx pointer to a draw context
|
||||
* @param dsc pointer to an initialized blend descriptor
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_SW_BLEND_H*/
|
||||
213
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_dither.c
Normal file
213
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_dither.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @file lv_draw_sw_dither.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sw_dither.h"
|
||||
#include "lv_draw_sw_gradient.h"
|
||||
#include "../../misc/lv_color.h"
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
#if _DITHER_GRADIENT
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_none(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w)
|
||||
{
|
||||
LV_UNUSED(x);
|
||||
LV_UNUSED(y);
|
||||
if(grad == NULL || grad->filled) return;
|
||||
for(lv_coord_t i = 0; i < w; i++) {
|
||||
grad->map[i] = lv_color_hex(grad->hmap[i].full);
|
||||
}
|
||||
grad->filled = 1;
|
||||
}
|
||||
|
||||
static const uint8_t dither_ordered_threshold_matrix[8 * 8] = {
|
||||
0, 48, 12, 60, 3, 51, 15, 63,
|
||||
32, 16, 44, 28, 35, 19, 47, 31,
|
||||
8, 56, 4, 52, 11, 59, 7, 55,
|
||||
40, 24, 36, 20, 43, 27, 39, 23,
|
||||
2, 50, 14, 62, 1, 49, 13, 61,
|
||||
34, 18, 46, 30, 33, 17, 45, 29,
|
||||
10, 58, 6, 54, 9, 57, 5, 53,
|
||||
42, 26, 38, 22, 41, 25, 37, 21
|
||||
}; /* Shift by 6 to normalize */
|
||||
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_hor(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w)
|
||||
{
|
||||
LV_UNUSED(x);
|
||||
/* For vertical dithering, the error is spread on the next column (and not next line).
|
||||
Since the renderer is scanline based, it's not obvious what could be used to perform the rendering efficiently.
|
||||
The algorithm below is based on few assumptions:
|
||||
1. An error diffusion algorithm (like Floyd Steinberg) here would be hard to implement since it means that a pixel on column n depends on the pixel on row n
|
||||
2. Instead an ordered dithering algorithm shift the value a bit, but the influence only spread from the matrix size (used 8x8 here)
|
||||
3. It means that a pixel i,j only depends on the value of a pixel i-7, j-7 to i,j and no other one.
|
||||
Then we compute a complete row of ordered dither and store it in out. */
|
||||
|
||||
/*The apply the algorithm for this patch*/
|
||||
for(lv_coord_t j = 0; j < w; j++) {
|
||||
int8_t factor = dither_ordered_threshold_matrix[(y & 7) * 8 + ((j) & 7)] - 32;
|
||||
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, j - 4, grad->size)];
|
||||
lv_color32_t t;
|
||||
t.ch.red = LV_CLAMP(0, tmp.ch.red + factor, 255);
|
||||
t.ch.green = LV_CLAMP(0, tmp.ch.green + factor, 255);
|
||||
t.ch.blue = LV_CLAMP(0, tmp.ch.blue + factor, 255);
|
||||
|
||||
grad->map[j] = lv_color_hex(t.full);
|
||||
}
|
||||
}
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_ver(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w)
|
||||
{
|
||||
/* For vertical dithering, the error is spread on the next column (and not next line).
|
||||
Since the renderer is scanline based, it's not obvious what could be used to perform the rendering efficiently.
|
||||
The algorithm below is based on few assumptions:
|
||||
1. An error diffusion algorithm (like Floyd Steinberg) here would be hard to implement since it means that a pixel on column n depends on the pixel on row n
|
||||
2. Instead an ordered dithering algorithm shift the value a bit, but the influence only spread from the matrix size (used 8x8 here)
|
||||
3. It means that a pixel i,j only depends on the value of a pixel i-7, j-7 to i,j and no other one.
|
||||
Then we compute a complete row of ordered dither and store it in out. */
|
||||
|
||||
/*Extract patch for working with, selected pseudo randomly*/
|
||||
lv_color32_t tmp = grad->hmap[LV_CLAMP(0, y - 4, grad->size)];
|
||||
|
||||
/*The apply the algorithm for this patch*/
|
||||
for(lv_coord_t j = 0; j < 8; j++) {
|
||||
int8_t factor = dither_ordered_threshold_matrix[(y & 7) * 8 + ((j + x) & 7)] - 32;
|
||||
lv_color32_t t;
|
||||
t.ch.red = LV_CLAMP(0, tmp.ch.red + factor, 255);
|
||||
t.ch.green = LV_CLAMP(0, tmp.ch.green + factor, 255);
|
||||
t.ch.blue = LV_CLAMP(0, tmp.ch.blue + factor, 255);
|
||||
|
||||
grad->map[j] = lv_color_hex(t.full);
|
||||
}
|
||||
/*Finally fill the line*/
|
||||
lv_coord_t j = 8;
|
||||
for(; j < w - 8; j += 8) {
|
||||
lv_memcpy(grad->map + j, grad->map, 8 * sizeof(*grad->map));
|
||||
}
|
||||
/* Prevent overwriting */
|
||||
for(; j < w; j++) {
|
||||
grad->map[j] = grad->map[j & 7];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if LV_DITHER_ERROR_DIFFUSION == 1
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(lv_grad_t * grad, lv_coord_t xs, lv_coord_t y, lv_coord_t w)
|
||||
{
|
||||
LV_UNUSED(xs);
|
||||
LV_UNUSED(y);
|
||||
LV_UNUSED(w);
|
||||
|
||||
/* Implement Floyd Steinberg algorithm, see https://surma.dev/things/ditherpunk/
|
||||
Coefs are: x 7
|
||||
3 5 1
|
||||
/ 16
|
||||
Can be implemented as: x (x<<3 - x)
|
||||
(x<<2 - x) (x<<2+x) x
|
||||
*/
|
||||
int coef[4] = {0, 0, 0, 0};
|
||||
#define FS_COMPUTE_ERROR(e) { coef[0] = (e<<3) - e; coef[1] = (e<<2) - e; coef[2] = (e<<2) + e; coef[3] = e; }
|
||||
#define FS_COMPONENTS(A, OP, B, C) A.ch.red = LV_CLAMP(0, A.ch.red OP B.r OP C.r, 255); A.ch.green = LV_CLAMP(0, A.ch.green OP B.g OP C.g, 255); A.ch.blue = LV_CLAMP(0, A.ch.blue OP B.b OP C.b, 255);
|
||||
#define FS_QUANT_ERROR(e, t, q) { lv_color32_t u; u.full = lv_color_to32(q); e.r = (int8_t)(t.ch.red - u.ch.red); e.g = (int8_t)(t.ch.green - u.ch.green); e.b = (int8_t)(t.ch.blue - u.ch.blue); }
|
||||
lv_scolor24_t next_px_err = {0}, next_l = {0}, error;
|
||||
/*First last pixel are not dithered */
|
||||
grad->map[0] = lv_color_hex(grad->hmap[0].full);
|
||||
for(lv_coord_t x = 1; x < grad->size - 1; x++) {
|
||||
lv_color32_t t = grad->hmap[x];
|
||||
lv_color_t q;
|
||||
/*Add error term*/
|
||||
FS_COMPONENTS(t, +, next_px_err, next_l);
|
||||
next_l = grad->error_acc[x + 1];
|
||||
/*Quantify*/
|
||||
q = lv_color_hex(t.full);
|
||||
/*Then compute error*/
|
||||
FS_QUANT_ERROR(error, t, q);
|
||||
/*Dither the error*/
|
||||
FS_COMPUTE_ERROR(error.r);
|
||||
next_px_err.r = coef[0] >> 4;
|
||||
grad->error_acc[x - 1].r += coef[1] >> 4;
|
||||
grad->error_acc[x].r += coef[2] >> 4;
|
||||
grad->error_acc[x + 1].r = coef[3] >> 4;
|
||||
|
||||
FS_COMPUTE_ERROR(error.g);
|
||||
next_px_err.g = coef[0] >> 4;
|
||||
grad->error_acc[x - 1].g += coef[1] >> 4;
|
||||
grad->error_acc[x].g += coef[2] >> 4;
|
||||
grad->error_acc[x + 1].g = coef[3] >> 4;
|
||||
|
||||
FS_COMPUTE_ERROR(error.b);
|
||||
next_px_err.b = coef[0] >> 4;
|
||||
grad->error_acc[x - 1].b += coef[1] >> 4;
|
||||
grad->error_acc[x].b += coef[2] >> 4;
|
||||
grad->error_acc[x + 1].b = coef[3] >> 4;
|
||||
|
||||
grad->map[x] = q;
|
||||
}
|
||||
grad->map[grad->size - 1] = lv_color_hex(grad->hmap[grad->size - 1].full);
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_ver(lv_grad_t * grad, lv_coord_t xs, lv_coord_t y, lv_coord_t w)
|
||||
{
|
||||
/* Try to implement error diffusion on a vertical gradient and an horizontal map using those tricks:
|
||||
Since the given hi-resolution gradient (in src) is vertical, the Floyd Steinberg algorithm pass need to be rotated,
|
||||
so we'll get this instead (from top to bottom):
|
||||
|
||||
A B C
|
||||
1 [ ][ ][ ]
|
||||
2 [ ][ ][ ] Pixel A2 will spread its error on pixel A3 with coefficient 7,
|
||||
3 [ ][ ][ ] Pixel A2 will spread its error on pixel B1 with coefficient 3, B2 with coef 5 and B3 with coef 1
|
||||
|
||||
When taking into account an arbitrary pixel P(i,j), its added error diffusion term is:
|
||||
e(i,j) = 1/16 * [ e(i-1,j) * 5 + e(i-1,j+1) * 3 + e(i-1,j-1) * 1 + e(i,j-1) * 7]
|
||||
|
||||
This means that the error term depends on pixel W, NW, N and SW.
|
||||
If we consider that we are generating the error diffused gradient map from top to bottom, we can remember the previous
|
||||
line (N, NW) in the term above. Also, we remember the (W) term too since we are computing the gradient map from left to right.
|
||||
However, the SW term is painful for us, we can't support it (since to get it, we need its own SW term and so on).
|
||||
Let's remove it and re-dispatch the error factor accordingly so they stays normalized:
|
||||
e(i,j) ~= 1/16 * [ e(i-1,j) * 6 + e(i-1,j-1) * 1 + e(i,j-1) * 9]
|
||||
|
||||
That's the idea of this pseudo Floyd Steinberg dithering */
|
||||
#define FS_APPLY(d, s, c) d.r = (int8_t)(s.r * c) >> 4; d.g = (int8_t)(s.g * c) >> 4; d.b = (int8_t)(s.b * c) >> 4;
|
||||
#define FS_COMPONENTS3(A, OP, B, b, C, c, D, d) \
|
||||
A.ch.red = LV_CLAMP(0, A.ch.red OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255); \
|
||||
A.ch.green = LV_CLAMP(0, A.ch.green OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255); \
|
||||
A.ch.blue = LV_CLAMP(0, A.ch.blue OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255);
|
||||
|
||||
lv_scolor24_t next_px_err, prev_l = grad->error_acc[0];
|
||||
/*Compute the error term for the current pixel (first pixel is never dithered)*/
|
||||
if(xs == 0) {
|
||||
grad->map[0] = lv_color_hex(grad->hmap[y].full);
|
||||
FS_QUANT_ERROR(next_px_err, grad->hmap[y], grad->map[0]);
|
||||
}
|
||||
else {
|
||||
lv_color_t tmp = lv_color_hex(grad->hmap[y].full);
|
||||
lv_color32_t t = grad->hmap[y];
|
||||
FS_QUANT_ERROR(next_px_err, grad->hmap[y], tmp);
|
||||
FS_COMPONENTS3(t, +, next_px_err, 6, prev_l, 1, grad->error_acc[0], 9);
|
||||
grad->map[0] = lv_color_hex(t.full);
|
||||
}
|
||||
|
||||
for(lv_coord_t x = 1; x < w; x++) {
|
||||
lv_color32_t t = grad->hmap[y];
|
||||
lv_color_t q;
|
||||
/*Add the current error term*/
|
||||
FS_COMPONENTS3(t, +, next_px_err, 6, prev_l, 1, grad->error_acc[x], 9);
|
||||
prev_l = grad->error_acc[x];
|
||||
/*Quantize and compute error term*/
|
||||
q = lv_color_hex(t.full);
|
||||
FS_QUANT_ERROR(next_px_err, t, q);
|
||||
/*Store error for next line computation*/
|
||||
grad->error_acc[x] = next_px_err;
|
||||
grad->map[x] = q;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
70
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_dither.h
Normal file
70
LVGL.Simulator/lvgl/src/draw/sw/lv_draw_sw_dither.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file lv_draw_sw_dither.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_SW_DITHER_H
|
||||
#define LV_DRAW_SW_DITHER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../core/lv_obj_pos.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if LV_COLOR_DEPTH < 32 && LV_DITHER_GRADIENT == 1
|
||||
#define _DITHER_GRADIENT 1
|
||||
#else
|
||||
#define _DITHER_GRADIENT 0
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
#if _DITHER_GRADIENT
|
||||
/*A signed error color component*/
|
||||
typedef struct {
|
||||
int8_t r, g, b;
|
||||
} lv_scolor24_t;
|
||||
|
||||
struct _lv_gradient_cache_t;
|
||||
typedef void (*lv_dither_func_t)(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**********************
|
||||
* PROTOTYPES
|
||||
**********************/
|
||||
#if LV_DRAW_COMPLEX
|
||||
#if _DITHER_GRADIENT
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_none(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
|
||||
const lv_coord_t y, const lv_coord_t w);
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
|
||||
const lv_coord_t y, const lv_coord_t w);
|
||||
|
||||
#if LV_DITHER_ERROR_DIFFUSION == 1
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
|
||||
const lv_coord_t y, const lv_coord_t w);
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs,
|
||||
const lv_coord_t y, const lv_coord_t w);
|
||||
#endif /* LV_DITHER_ERROR_DIFFUSION */
|
||||
|
||||
#endif /* _DITHER_GRADIENT */
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user