1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

refactor(event) simplify cover check realted event functions

This commit is contained in:
Gabor Kiss-Vamosi 2021-05-15 00:14:31 +02:00
parent b7f875aba6
commit 94a47dc6d9
10 changed files with 64 additions and 60 deletions

View File

@ -177,37 +177,25 @@ Finish the drawing of a part. It's a good place to draw extra content on the par
This event is used to check whether an object fully covers an area or not.
`lv_event_get_cover_check_info(event)` returns an pointer to an `lv_cover_check_info_t` variable. Its `res` field should be set to the following values considering the `area` field:
- `LV_DRAW_RES_COVER` the areas is fully covered by the object
- `LV_DRAW_RES_NOT_COVER` the areas is not covered by the object
- `LV_DRAW_RES_MASKED` there is a mask on the object so it can not covert the area
`lv_event_get_cover_area(event)` returns an pointer to an area to check and `lv_event_set_cover_res(event, res)` can be used to set one of these results:
- `LV_COVER_RES_COVER` the areas is fully covered by the object
- `LV_COVER_RES_NOT_COVER` the areas is not covered by the object
- `LV_COVER_RES_MASKED` there is a mask on the object so it can not covert the area
Here are some cases why can't an object fully cover an area:
- It's simply not fully on the that area
- It has radius
- It has not 100% background opacity
- It's an ARGB or chroma keyed image
- It's a text
- It has not normal blending mode. In this case LVGL needs to know the colors under the object to make the blending properly
- It's a text, etc
In short if for any reason the the area below the object is visible than it doesn't cover that area.
Some guideline how to set the `res` field in `lv_cover_check_info_t`:
- Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called.
- You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events.
Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called.
You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events.
E.g. if a widget has > 0 radius it might not cover an area but you need to handle `radius` only if you will modify it and widget can't know about it.
- If `res` is already set to `LV_DRAW_RES_MASKED` do nothing. In this case an other event already set it and it's the "strongest" state that shouldn't be overwritten.
- If you added a draw mask on the object set `res` to `LV_DRAW_RES_MASKED`
- If there is no draw masks but the object simply not covers the area for any reason set `LV_DRAW_RES_NOT_COVER`
- If the area is fully covered by the object leave `res` unchanged.
In the practice probably you need to set only `LV_DRAW_RES_MASKED`if you added masks in a MAIN or POST draw events because "normal" cover checks are handles by the widgets.
However, if you really added masks in MAIN or POST draw events you need to handle `LV_EVENT_COVER_CHECK` event and tell LVGL there are masks on this object.
If masks are added and removed in `LV_EVENT_DRAW_PART_BEGIN/END`, `LV_EVENT_COVER_CHECK` doesn't need to know about it except the masks affects `LV_PART_MAIN`.
It's because LVGL checks the main part to decide whether an object covers an area or not.
So it doesn't matter e.g. if a tabel's cell is masked because the tables background already covered the area or not.
#### LV_EVENT_REFR_EXT_DRAW_SIZE

View File

@ -319,13 +319,25 @@ lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
}
}
lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e)
const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
{
if(e->code == LV_EVENT_COVER_CHECK) {
return lv_event_get_param(e);
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(p->res == LV_COVER_RES_MASKED) return; /*Do not overwrite masked result*/
if(res == LV_COVER_RES_NOT_COVER) p->res = res;
} else {
LV_LOG_WARN("Not interpreted with this event code");
return 0;
}
}

View File

@ -113,15 +113,12 @@ typedef struct {
/**
* Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not.
* `res` should be set like this:
* - If already set to ::LV_DRAW_RES_MASKED do nothing
* - If there is a draw mask on the object set to ::LV_DRAW_RES_MASKED
* - If there is no draw mask but the object simply not covers the area set ::LV_DRAW_RES_NOT_COVER
* - If the area is fully covered by the object leave `res` unchanged.
* 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_draw_res_t res; /**< Set to ::LV_DRAW_RES_NOT_COVER or ::LV_DRAW_RES_MASKED. */
const lv_area_t * area; /**< The area to check */
lv_cover_res_t res;
const lv_area_t * area;
} lv_cover_check_info_t;
/**********************
@ -290,12 +287,19 @@ lv_point_t * lv_event_get_self_size_info(lv_event_t * e);
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e);
/**
* Get a pointer to an `lv_cover_check_info_t` variable in which the area cover information should be saved.
* Can be used in `LV_EVENT_COVER_CHECK`
* 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 pointer to `lv_cover_check_info_t` or NULL if called on an unrelated event
* @return an area with absolute coordinates to check
*/
lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e);
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

View File

@ -454,9 +454,9 @@ static void lv_obj_draw(lv_event_t * 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_DRAW_RES_MASKED) return;
if(info->res == LV_COVER_RES_MASKED) return;
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
info->res = LV_DRAW_RES_MASKED;
info->res = LV_COVER_RES_MASKED;
return;
}
@ -472,27 +472,27 @@ static void lv_obj_draw(lv_event_t * e)
coords.y2 += h;
if(_lv_area_is_in(info->area, &coords, r) == false) {
info->res = LV_DRAW_RES_NOT_COVER;
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_DRAW_RES_NOT_COVER;
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_DRAW_RES_NOT_COVER;
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_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
info->res = LV_DRAW_RES_COVER;
info->res = LV_COVER_RES_COVER;
}
else if(code == LV_EVENT_DRAW_MAIN) {

View File

@ -25,12 +25,12 @@ extern "C" {
struct _lv_obj_t;
/** Design results*/
/** Cover check results*/
typedef enum {
LV_DRAW_RES_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is fully covered*/
LV_DRAW_RES_NOT_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is not covered*/
LV_DRAW_RES_MASKED, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is masked out*/
}lv_draw_res_t;
LV_COVER_RES_COVER,
LV_COVER_RES_NOT_COVER,
LV_COVER_RES_MASKED,
}lv_cover_res_t;
typedef struct
{

View File

@ -574,10 +574,10 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
/*If this object is fully cover the draw area check the children too*/
if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) {
lv_cover_check_info_t info;
info.res = LV_DRAW_RES_COVER;
info.res = LV_COVER_RES_COVER;
info.area = area_p;
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
if(info.res == LV_DRAW_RES_MASKED) return NULL;
if(info.res == LV_COVER_RES_MASKED) return NULL;
uint32_t i;
for(i = 0; i < lv_obj_get_child_cnt(obj); i++) {
@ -592,7 +592,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
/*If no better children use this object*/
if(found_p == NULL) {
if(info.res == LV_DRAW_RES_COVER) {
if(info.res == LV_COVER_RES_COVER) {
found_p = obj;
}
}

View File

@ -520,7 +520,7 @@ static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e)
}
else if(code == LV_EVENT_COVER_CHECK) {
lv_cover_check_info_t * info = lv_event_get_param(e);
if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER;
if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER;
}
}

View File

@ -180,7 +180,7 @@ static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e)
}
else if(code == LV_EVENT_COVER_CHECK) {
lv_cover_check_info_t * info = lv_event_get_param(e);
if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER;
if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER;
}
}

View File

@ -490,21 +490,21 @@ static void draw_img(lv_event_t * e)
lv_img_t * img = (lv_img_t *)obj;
if(code == LV_EVENT_COVER_CHECK) {
lv_cover_check_info_t * info = lv_event_get_param(e);
if(info->res == LV_DRAW_RES_MASKED) return;
if(info->res == LV_COVER_RES_MASKED) return;
if(img->src_type == LV_IMG_SRC_UNKNOWN || img->src_type == LV_IMG_SRC_SYMBOL) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
/*Non true color format might have "holes"*/
if(img->cf != LV_IMG_CF_TRUE_COLOR && img->cf != LV_IMG_CF_RAW) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
/*With not LV_OPA_COVER images can't cover an area */
if(lv_obj_get_style_img_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
@ -512,7 +512,7 @@ static void draw_img(lv_event_t * e)
angle_final += img->angle;
if(angle_final != 0) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
@ -523,7 +523,7 @@ static void draw_img(lv_event_t * e)
const lv_area_t * clip_area = lv_event_get_param(e);
if(zoom_final == LV_IMG_ZOOM_NONE) {
if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
}
@ -536,7 +536,7 @@ static void draw_img(lv_event_t * e)
a.y2 += obj->coords.y1;
if(_lv_area_is_in(clip_area, &a, 0) == false) {
info->res = LV_DRAW_RES_NOT_COVER;
info->res = LV_COVER_RES_NOT_COVER;
return;
}
}

View File

@ -196,7 +196,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area
{
/*Return false if the object is not covers the mask_p area*/
if(mode == LV_DRAW_COVER_CHK) {
return LV_DRAW_RES_NOT_COVER;
return LV_COVER_RES_NOT_COVER;
}
/*Draw the object*/
else if(mode == LV_DRAW_DRAW_MAIN) {
@ -206,7 +206,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area
else if(mode == LV_DRAW_DRAW_POST) {
}
return LV_DRAW_RES_OK;
return LV_COVER_RES_OK;
}
/**