feat(draw): support transforming widgets and improfe sw transform

For details see: https://docs.lvgl.io/master/overview/style.html
This commit is contained in:
Gabor Kiss-Vamosi
2022-04-26 10:45:12 +02:00
parent 69aa421acd
commit 318146a2c2
48 changed files with 1804 additions and 1117 deletions

View File

@@ -26,6 +26,7 @@
static lv_coord_t calc_content_width(lv_obj_t * obj);
static lv_coord_t calc_content_height(lv_obj_t * obj);
static void layout_update_core(lv_obj_t * obj);
static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv);
/**********************
* STATIC VARIABLES
@@ -206,6 +207,8 @@ bool lv_obj_refr_size(lv_obj_t * obj)
bool on2 = _lv_area_is_in(&obj->coords, &parent_fit_area, 0);
if(on1 || (!on1 && on2)) lv_obj_scrollbar_invalidate(parent);
lv_obj_refresh_ext_draw_size(obj);
return true;
}
@@ -627,6 +630,7 @@ void lv_obj_refr_pos(lv_obj_t * obj)
{
if(lv_obj_is_layout_positioned(obj)) return;
lv_obj_t * parent = lv_obj_get_parent(obj);
lv_coord_t x = lv_obj_get_style_x(obj, LV_PART_MAIN);
lv_coord_t y = lv_obj_get_style_y(obj, LV_PART_MAIN);
@@ -791,6 +795,41 @@ void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_dif
}
}
void lv_obj_transform_point(const lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv)
{
if(obj) {
if(inv) {
if(recursive) lv_obj_transform_point(lv_obj_get_parent(obj), p, recursive, inv);
transform_point(obj, p, inv);
}
else {
transform_point(obj, p, inv);
if(recursive) lv_obj_transform_point(lv_obj_get_parent(obj), p, recursive, inv);
}
}
}
void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, bool recursive,
bool inv)
{
lv_point_t p[4] = {
{area->x1, area->y1},
{area->x1, area->y2},
{area->x2, area->y1},
{area->x2, area->y2},
};
lv_obj_transform_point(obj, &p[0], recursive, inv);
lv_obj_transform_point(obj, &p[1], recursive, inv);
lv_obj_transform_point(obj, &p[2], recursive, inv);
lv_obj_transform_point(obj, &p[3], recursive, inv);
area->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x);
area->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x);
area->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y);
area->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y);
lv_area_increase(area, 5, 5);
}
void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area)
{
@@ -798,21 +837,15 @@ void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area)
lv_area_t area_tmp;
lv_area_copy(&area_tmp, area);
bool visible = lv_obj_area_is_visible(obj, &area_tmp);
if(!lv_obj_area_is_visible(obj, &area_tmp)) return;
if(visible) _lv_inv_area(lv_obj_get_disp(obj), &area_tmp);
_lv_inv_area(lv_obj_get_disp(obj), &area_tmp);
}
void lv_obj_invalidate(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
/*If the object has overflow visible it can be drawn anywhere on its parent
*It needs to be checked recursively*/
while(lv_obj_get_parent(obj) && lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
obj = lv_obj_get_parent(obj);
}
/*Truncate the area to the object*/
lv_area_t obj_coords;
lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj);
@@ -841,7 +874,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
}
/*Truncate the area to the object*/
if(!lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
if(!lv_obj_has_flag_any(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
lv_area_t obj_coords;
lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj);
lv_area_copy(&obj_coords, &obj->coords);
@@ -854,6 +887,9 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
if(!_lv_area_intersect(area, area, &obj_coords)) return false;
}
lv_obj_get_transformed_area(obj, area, true, false);
/*Truncate recursively to the parents*/
lv_obj_t * par = lv_obj_get_parent(obj);
while(par != NULL) {
@@ -861,8 +897,10 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false;
/*Truncate to the parent and if no common parts break*/
if(!lv_obj_has_flag(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
if(!_lv_area_intersect(area, area, &par->coords)) return false;
if(!lv_obj_has_flag_any(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
lv_area_t par_area = par->coords;
lv_obj_get_transformed_area(par, &par_area, true, false);
if(!_lv_area_intersect(area, area, &par_area)) return false;
}
par = lv_obj_get_parent(par);
@@ -1108,3 +1146,19 @@ static void layout_update_core(lv_obj_t * obj)
}
}
}
static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv)
{
lv_point_t pivot;
pivot.x = obj->coords.x1 + lv_obj_get_style_transform_pivot_x(obj, 0);
pivot.y = obj->coords.y1 + lv_obj_get_style_transform_pivot_y(obj, 0);
int16_t angle = lv_obj_get_style_transform_angle(obj, 0);
int16_t zoom = lv_obj_get_style_transform_zoom(obj, 0);
if(inv) {
angle = -angle;
zoom = (256 * 256) / zoom;
}
lv_point_transform(p, angle, zoom, &pivot);
}