mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(arc): add lv_draw_arc_get_area to have a common function to get the area to invalidated
This commit is contained in:
parent
8106c2f348
commit
0aec010a52
@ -67,17 +67,6 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc)
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
@ -219,6 +208,82 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uin
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
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 * inv_area)
|
||||
{
|
||||
lv_coord_t rout = radius;
|
||||
lv_coord_t rin = radius - w;
|
||||
lv_coord_t extra_area = rounded ? w : 0;
|
||||
uint8_t start_quarter = start_angle / 90;
|
||||
uint8_t end_quarter = end_angle / 90;
|
||||
|
||||
|
||||
if(start_quarter == end_quarter && start_angle <= end_angle) {
|
||||
if(start_quarter == 0) {
|
||||
inv_area->y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
inv_area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 1) {
|
||||
inv_area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
inv_area->y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 2) {
|
||||
inv_area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
inv_area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3) {
|
||||
inv_area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
|
||||
inv_area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_area->y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
}
|
||||
else if(start_quarter == 0 && end_quarter == 1) {
|
||||
inv_area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle),
|
||||
lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_area->y2 = y + rout + extra_area;
|
||||
}
|
||||
else if(start_quarter == 1 && end_quarter == 2) {
|
||||
inv_area->x1 = x - rout - extra_area;
|
||||
inv_area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90),
|
||||
lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 2 && end_quarter == 3) {
|
||||
inv_area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->y1 = y - rout - extra_area;
|
||||
inv_area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
inv_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) {
|
||||
inv_area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90),
|
||||
lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
inv_area->x2 = x + rout + extra_area;
|
||||
inv_area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
}
|
||||
else {
|
||||
inv_area->x1 = x - rout;
|
||||
inv_area->y1 = y - rout;
|
||||
inv_area->x2 = x + rout;
|
||||
inv_area->y2 = y + rout;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
@ -40,18 +40,30 @@ LV_ATTRIBUTE_FAST_MEM 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
|
||||
* @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(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange
|
||||
* @param x the x coordinate of the center of the arc
|
||||
* @param y the y coordinate of the center of the arc
|
||||
* @param radius the radius of the arc
|
||||
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
|
||||
* @param end_angle the end angle of the arc
|
||||
* @param w width of the arc
|
||||
* @param rounded true: the arc is rounded
|
||||
* @param result 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 * result);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
@ -33,6 +33,8 @@ static lv_draw_res_t lv_meter_draw(lv_obj_t * lmeter, const lv_area_t * clip_are
|
||||
static void draw_arcs(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area_t * scale_area);
|
||||
static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area_t * scale_area);
|
||||
static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area_t * scale_area);
|
||||
static lv_meter_scale_t * get_scale_of_indic(lv_obj_t * obj, lv_meter_indicator_t * indic);
|
||||
static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -187,21 +189,41 @@ lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t
|
||||
|
||||
void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value)
|
||||
{
|
||||
int32_t old_start = indic->start_value;
|
||||
int32_t old_end = indic->end_value;
|
||||
indic->start_value = value;
|
||||
indic->end_value = value;
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(indic->type == LV_METER_INDICATOR_TYPE_ARC) {
|
||||
inv_arc(obj, indic, old_start, value);
|
||||
inv_arc(obj, indic, old_end, value);
|
||||
} else {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value)
|
||||
{
|
||||
int32_t old_value = indic->start_value;
|
||||
indic->start_value = value;
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(indic->type == LV_METER_INDICATOR_TYPE_ARC) {
|
||||
inv_arc(obj, indic, old_value, value);
|
||||
} else {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value)
|
||||
{
|
||||
int32_t old_value = indic->end_value;
|
||||
indic->end_value = value;
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(indic->type == LV_METER_INDICATOR_TYPE_ARC) {
|
||||
inv_arc(obj, indic, old_value, value);
|
||||
} else {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
@ -581,4 +603,48 @@ static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_a
|
||||
}
|
||||
}
|
||||
|
||||
static lv_meter_scale_t * get_scale_of_indic(lv_obj_t * obj, lv_meter_indicator_t * indic)
|
||||
{
|
||||
lv_meter_t * meter = (lv_meter_t *)obj;
|
||||
|
||||
lv_meter_scale_t * scale;
|
||||
|
||||
_LV_LL_READ_BACK(&meter->scale_ll, scale) {
|
||||
lv_meter_indicator_t * ind;
|
||||
_LV_LL_READ_BACK(&scale->indicator_ll, ind) {
|
||||
if(ind == indic) return scale;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value)
|
||||
{
|
||||
bool rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS);
|
||||
|
||||
lv_area_t scale_area;
|
||||
lv_obj_get_coords(obj, &scale_area);
|
||||
scale_area.x1 += lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
scale_area.y1 += lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
scale_area.x2 -= lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
scale_area.y2 -= lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
|
||||
lv_coord_t r_out = lv_area_get_width(&scale_area) / 2;
|
||||
lv_point_t scale_center;
|
||||
scale_center.x = scale_area.x1 + r_out;
|
||||
scale_center.y = scale_area.y1 + r_out;
|
||||
|
||||
r_out += indic->type_data.arc.r_mod;
|
||||
|
||||
lv_meter_scale_t * scale = get_scale_of_indic(obj, indic);
|
||||
|
||||
int32_t start_angle = lv_map(old_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation);
|
||||
int32_t end_angle = lv_map(new_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation);
|
||||
lv_area_t a;
|
||||
lv_draw_arc_get_area(scale_center.x, scale_center.y, r_out, LV_MIN(start_angle, end_angle), LV_MAX(start_angle, end_angle), indic->type_data.arc.width, rounded, &a);
|
||||
lv_obj_invalidate_area(obj, &a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user