mirror of
https://github.com/lvgl/lvgl.git
synced 2026-09-25 16:44:03 +08:00
perf(arc): optimize angle invalidation (esp. for spinner, or when invisible) (#10307)
This commit is contained in:
+91
-81
@@ -42,6 +42,7 @@ static void lv_arc_draw(lv_event_t * e);
|
||||
static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
static void inv_arc_area(lv_obj_t * arc, lv_value_precise_t start_angle, lv_value_precise_t end_angle, lv_part_t part);
|
||||
static void inv_knob_area(lv_obj_t * obj);
|
||||
static void get_knob_inv_area(lv_obj_t * obj, lv_area_t * area);
|
||||
static void get_center(const lv_obj_t * obj, lv_point_t * center, int32_t * arc_r);
|
||||
static lv_value_precise_t get_angle(const lv_obj_t * obj);
|
||||
static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, int32_t r, lv_area_t * knob_area);
|
||||
@@ -162,52 +163,59 @@ void lv_arc_set_start_angle(lv_obj_t * obj, lv_value_precise_t start)
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(start > 360) start -= 360;
|
||||
|
||||
lv_value_precise_t old_delta = arc->indic_angle_end - arc->indic_angle_start;
|
||||
lv_value_precise_t new_delta = arc->indic_angle_end - start;
|
||||
|
||||
if(old_delta < 0) old_delta = 360 + old_delta;
|
||||
if(new_delta < 0) new_delta = 360 + new_delta;
|
||||
|
||||
if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(new_delta < old_delta) inv_arc_area(obj, arc->indic_angle_start, start, LV_PART_INDICATOR);
|
||||
else if(old_delta < new_delta) inv_arc_area(obj, start, arc->indic_angle_start, LV_PART_INDICATOR);
|
||||
|
||||
inv_knob_area(obj);
|
||||
|
||||
arc->indic_angle_start = start;
|
||||
|
||||
inv_knob_area(obj);
|
||||
lv_arc_set_angles(obj, start, arc->indic_angle_end);
|
||||
}
|
||||
|
||||
void lv_arc_set_end_angle(lv_obj_t * obj, lv_value_precise_t end)
|
||||
{
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
if(end > 360) end -= 360;
|
||||
|
||||
lv_value_precise_t old_delta = arc->indic_angle_end - arc->indic_angle_start;
|
||||
lv_value_precise_t new_delta = end - arc->indic_angle_start;
|
||||
|
||||
if(old_delta < 0) old_delta = 360 + old_delta;
|
||||
if(new_delta < 0) new_delta = 360 + new_delta;
|
||||
|
||||
if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(new_delta < old_delta) inv_arc_area(obj, end, arc->indic_angle_end, LV_PART_INDICATOR);
|
||||
else if(old_delta < new_delta) inv_arc_area(obj, arc->indic_angle_end, end, LV_PART_INDICATOR);
|
||||
|
||||
inv_knob_area(obj);
|
||||
|
||||
arc->indic_angle_end = end;
|
||||
|
||||
inv_knob_area(obj);
|
||||
lv_arc_set_angles(obj, arc->indic_angle_start, end);
|
||||
}
|
||||
|
||||
void lv_arc_set_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end)
|
||||
{
|
||||
lv_arc_set_end_angle(obj, end);
|
||||
lv_arc_set_start_angle(obj, start);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(start > 360) start -= 360;
|
||||
if(end > 360) end -= 360;
|
||||
|
||||
/*Snapshot for invalidation*/
|
||||
lv_value_precise_t old_start = arc->indic_angle_start;
|
||||
lv_value_precise_t old_end = arc->indic_angle_end;
|
||||
lv_area_t old_knob_area;
|
||||
get_knob_inv_area(obj, &old_knob_area);
|
||||
|
||||
/*Apply the change*/
|
||||
arc->indic_angle_start = start;
|
||||
arc->indic_angle_end = end;
|
||||
|
||||
/*Invalidation*/
|
||||
if(lv_obj_is_visible(obj)) {
|
||||
/*Area swept by the start angle*/
|
||||
lv_value_precise_t start_old_delta = end - old_start;
|
||||
lv_value_precise_t start_new_delta = end - start;
|
||||
if(start_old_delta < 0) start_old_delta = 360 + start_old_delta;
|
||||
if(start_new_delta < 0) start_new_delta = 360 + start_new_delta;
|
||||
if(LV_ABS(start_new_delta - start_old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(start_new_delta < start_old_delta) inv_arc_area(obj, old_start, start, LV_PART_INDICATOR);
|
||||
else if(start_old_delta < start_new_delta) inv_arc_area(obj, start, old_start, LV_PART_INDICATOR);
|
||||
|
||||
/*Area swept by the end angle*/
|
||||
lv_value_precise_t end_old_delta = old_end - old_start;
|
||||
lv_value_precise_t end_new_delta = end - old_start;
|
||||
if(end_old_delta < 0) end_old_delta = 360 + end_old_delta;
|
||||
if(end_new_delta < 0) end_new_delta = 360 + end_new_delta;
|
||||
if(LV_ABS(end_new_delta - end_old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(end_new_delta < end_old_delta) inv_arc_area(obj, end, old_end, LV_PART_INDICATOR);
|
||||
else if(end_old_delta < end_new_delta) inv_arc_area(obj, old_end, end, LV_PART_INDICATOR);
|
||||
|
||||
/*Knob*/
|
||||
lv_obj_invalidate_area(obj, &old_knob_area);
|
||||
inv_knob_area(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_arc_set_bg_start_angle(lv_obj_t * obj, lv_value_precise_t start)
|
||||
@@ -215,21 +223,7 @@ void lv_arc_set_bg_start_angle(lv_obj_t * obj, lv_value_precise_t start)
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(start > 360) start -= 360;
|
||||
|
||||
lv_value_precise_t old_delta = arc->bg_angle_end - arc->bg_angle_start;
|
||||
lv_value_precise_t new_delta = arc->bg_angle_end - start;
|
||||
|
||||
if(old_delta < 0) old_delta = 360 + old_delta;
|
||||
if(new_delta < 0) new_delta = 360 + new_delta;
|
||||
|
||||
if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(new_delta < old_delta) inv_arc_area(obj, arc->bg_angle_start, start, LV_PART_MAIN);
|
||||
else if(old_delta < new_delta) inv_arc_area(obj, start, arc->bg_angle_start, LV_PART_MAIN);
|
||||
|
||||
arc->bg_angle_start = start;
|
||||
|
||||
value_update(obj);
|
||||
lv_arc_set_bg_angles(obj, start, arc->bg_angle_end);
|
||||
}
|
||||
|
||||
void lv_arc_set_bg_end_angle(lv_obj_t * obj, lv_value_precise_t end)
|
||||
@@ -237,27 +231,46 @@ void lv_arc_set_bg_end_angle(lv_obj_t * obj, lv_value_precise_t end)
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(end > 360) end -= 360;
|
||||
|
||||
lv_value_precise_t old_delta = arc->bg_angle_end - arc->bg_angle_start;
|
||||
lv_value_precise_t new_delta = end - arc->bg_angle_start;
|
||||
|
||||
if(old_delta < 0) old_delta = 360 + old_delta;
|
||||
if(new_delta < 0) new_delta = 360 + new_delta;
|
||||
|
||||
if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(new_delta < old_delta) inv_arc_area(obj, end, arc->bg_angle_end, LV_PART_MAIN);
|
||||
else if(old_delta < new_delta) inv_arc_area(obj, arc->bg_angle_end, end, LV_PART_MAIN);
|
||||
|
||||
arc->bg_angle_end = end;
|
||||
|
||||
value_update(obj);
|
||||
lv_arc_set_bg_angles(obj, arc->bg_angle_start, end);
|
||||
}
|
||||
|
||||
void lv_arc_set_bg_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end)
|
||||
{
|
||||
lv_arc_set_bg_end_angle(obj, end);
|
||||
lv_arc_set_bg_start_angle(obj, start);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(start > 360) start -= 360;
|
||||
if(end > 360) end -= 360;
|
||||
|
||||
/*Snapshot for invalidation*/
|
||||
lv_value_precise_t old_start = arc->bg_angle_start;
|
||||
lv_value_precise_t old_end = arc->bg_angle_end;
|
||||
|
||||
/*Apply the change*/
|
||||
arc->bg_angle_start = start;
|
||||
arc->bg_angle_end = end;
|
||||
value_update(obj);
|
||||
|
||||
/*Invalidation*/
|
||||
if(lv_obj_is_visible(obj)) {
|
||||
/*Area swept by the start angle*/
|
||||
lv_value_precise_t start_old_delta = end - old_start;
|
||||
lv_value_precise_t start_new_delta = end - start;
|
||||
if(start_old_delta < 0) start_old_delta = 360 + start_old_delta;
|
||||
if(start_new_delta < 0) start_new_delta = 360 + start_new_delta;
|
||||
if(LV_ABS(start_new_delta - start_old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(start_new_delta < start_old_delta) inv_arc_area(obj, old_start, start, LV_PART_MAIN);
|
||||
else if(start_old_delta < start_new_delta) inv_arc_area(obj, start, old_start, LV_PART_MAIN);
|
||||
|
||||
/*Area swept by the end angle*/
|
||||
lv_value_precise_t end_old_delta = old_end - old_start;
|
||||
lv_value_precise_t end_new_delta = end - old_start;
|
||||
if(end_old_delta < 0) end_old_delta = 360 + end_old_delta;
|
||||
if(end_new_delta < 0) end_new_delta = 360 + end_new_delta;
|
||||
if(LV_ABS(end_new_delta - end_old_delta) > 180) lv_obj_invalidate(obj);
|
||||
else if(end_new_delta < end_old_delta) inv_arc_area(obj, end, old_end, LV_PART_MAIN);
|
||||
else if(end_old_delta < end_new_delta) inv_arc_area(obj, old_end, end, LV_PART_MAIN);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_arc_set_rotation(lv_obj_t * obj, int32_t rotation)
|
||||
@@ -289,8 +302,7 @@ void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type)
|
||||
switch(arc->type) {
|
||||
case LV_ARC_MODE_SYMMETRICAL:
|
||||
bg_midpoint = (arc->bg_angle_start + bg_end) / 2;
|
||||
lv_arc_set_start_angle(obj, bg_midpoint);
|
||||
lv_arc_set_end_angle(obj, bg_midpoint);
|
||||
lv_arc_set_angles(obj, bg_midpoint, bg_midpoint);
|
||||
break;
|
||||
case LV_ARC_MODE_REVERSE:
|
||||
lv_arc_set_end_angle(obj, arc->bg_angle_end);
|
||||
@@ -864,10 +876,6 @@ static void lv_arc_draw(lv_event_t * e)
|
||||
static void inv_arc_area(lv_obj_t * obj, lv_value_precise_t start_angle, lv_value_precise_t end_angle, lv_part_t part)
|
||||
{
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
|
||||
/*Skip this complicated invalidation if the arc is not visible*/
|
||||
if(lv_obj_is_visible(obj) == false) return;
|
||||
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
if(start_angle == end_angle) return;
|
||||
@@ -898,21 +906,25 @@ static void inv_arc_area(lv_obj_t * obj, lv_value_precise_t start_angle, lv_valu
|
||||
lv_obj_invalidate_area(obj, &inv_area);
|
||||
}
|
||||
|
||||
static void inv_knob_area(lv_obj_t * obj)
|
||||
static void get_knob_inv_area(lv_obj_t * obj, lv_area_t * area)
|
||||
{
|
||||
lv_point_t c;
|
||||
int32_t r;
|
||||
get_center(obj, &c, &r);
|
||||
|
||||
lv_area_t a;
|
||||
get_knob_area(obj, &c, r, &a);
|
||||
get_knob_area(obj, &c, r, area);
|
||||
|
||||
int32_t knob_extra_size = knob_get_extra_size(obj);
|
||||
|
||||
if(knob_extra_size > 0) {
|
||||
lv_area_increase(&a, knob_extra_size, knob_extra_size);
|
||||
lv_area_increase(area, knob_extra_size, knob_extra_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void inv_knob_area(lv_obj_t * obj)
|
||||
{
|
||||
lv_area_t a;
|
||||
get_knob_inv_area(obj, &a);
|
||||
lv_obj_invalidate_area(obj, &a);
|
||||
}
|
||||
|
||||
@@ -1005,13 +1017,11 @@ static void value_update(lv_obj_t * obj)
|
||||
|
||||
if(arc->value < range_midpoint) {
|
||||
angle = lv_map(arc->value, arc->min_value, range_midpoint, (int32_t)arc->bg_angle_start, (int32_t)bg_midpoint);
|
||||
lv_arc_set_start_angle(obj, angle);
|
||||
lv_arc_set_end_angle(obj, bg_midpoint);
|
||||
lv_arc_set_angles(obj, angle, bg_midpoint);
|
||||
}
|
||||
else {
|
||||
angle = lv_map(arc->value, range_midpoint, arc->max_value, (int32_t)bg_midpoint, (int32_t)bg_end);
|
||||
lv_arc_set_start_angle(obj, bg_midpoint);
|
||||
lv_arc_set_end_angle(obj, angle);
|
||||
lv_arc_set_angles(obj, bg_midpoint, angle);
|
||||
}
|
||||
break;
|
||||
case LV_ARC_MODE_REVERSE:
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_spinner_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void arc_anim_start_angle(void * obj, int32_t v);
|
||||
static void arc_anim_end_angle(void * obj, int32_t v);
|
||||
static void arc_anim_angles(void * obj, int32_t v);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -98,17 +97,10 @@ void lv_spinner_set_anim_params(lv_obj_t * obj, uint32_t t, uint32_t angle)
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_exec_cb(&a, arc_anim_end_angle);
|
||||
lv_anim_set_exec_cb(&a, arc_anim_angles);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_duration(&a, t);
|
||||
lv_anim_set_values(&a, angle, 360 + angle);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_custom_bezier3);
|
||||
lv_anim_set_bezier3_param(&a, LV_BEZIER_VAL_FLOAT(0.42), LV_BEZIER_VAL_FLOAT(0.58),
|
||||
LV_BEZIER_VAL_FLOAT(0), LV_BEZIER_VAL_FLOAT(1));
|
||||
lv_anim_set_values(&a, 0, 360);
|
||||
lv_anim_set_exec_cb(&a, arc_anim_start_angle);
|
||||
lv_anim_set_values(&a, 0, LV_BEZIER_VAL_MAX);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_arc_set_bg_angles(obj, 0, 360);
|
||||
@@ -160,14 +152,19 @@ static void lv_spinner_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob
|
||||
lv_spinner_set_anim_params(obj, DEF_TIME, DEF_ARC_ANGLE);
|
||||
}
|
||||
|
||||
static void arc_anim_start_angle(void * obj, int32_t v)
|
||||
static void arc_anim_angles(void * obj, int32_t v)
|
||||
{
|
||||
lv_arc_set_start_angle(obj, (uint32_t) v);
|
||||
}
|
||||
lv_spinner_t * spinner = (lv_spinner_t *)obj;
|
||||
|
||||
static void arc_anim_end_angle(void * obj, int32_t v)
|
||||
{
|
||||
lv_arc_set_end_angle(obj, (uint32_t) v);
|
||||
/*Start angle (bezier)*/
|
||||
int32_t step = lv_cubic_bezier(v, LV_BEZIER_VAL_FLOAT(0.42f), LV_BEZIER_VAL_FLOAT(0.58f),
|
||||
LV_BEZIER_VAL_FLOAT(0.0f), LV_BEZIER_VAL_FLOAT(1.0f));
|
||||
lv_value_precise_t start = (lv_value_precise_t)((step * 360) >> LV_BEZIER_VAL_SHIFT);
|
||||
|
||||
/*End angle (linear)*/
|
||||
lv_value_precise_t end = spinner->angle + ((v * 360) >> LV_BEZIER_VAL_SHIFT);
|
||||
|
||||
lv_arc_set_angles(obj, start, end);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_SPINNER*/
|
||||
|
||||
Reference in New Issue
Block a user