Add arc antialiasing

This commit is contained in:
tgillbe
2019-10-16 19:13:10 +01:00
parent 27c8a88c94
commit 6cfb0af7c3
3 changed files with 98 additions and 14 deletions

View File

@@ -57,6 +57,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
lv_coord_t thickness = style->line.width;
if(thickness > radius) thickness = radius;
#if LV_ANTIALIAS
thickness--;
radius--;
#endif
lv_coord_t r_out = radius;
lv_coord_t r_in = r_out - thickness;
int16_t deg_base;
@@ -73,17 +78,26 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
else
deg_test = deg_test_inv;
int middle_r_out = r_out;
#if !LV_ANTIALIAS
thickness--;
middle_r_out = r_out - 1;
#endif
if(deg_test(270, start_angle, end_angle))
hor_line(center_x - r_out + 1, center_y, mask, thickness - 1, color, opa); /*Left Middle*/
hor_line(center_x - middle_r_out, center_y, mask, thickness, color, opa); /*Left Middle*/
if(deg_test(90, start_angle, end_angle))
hor_line(center_x + r_in, center_y, mask, thickness - 1, color, opa); /*Right Middle*/
hor_line(center_x + r_in, center_y, mask, thickness, color, opa); /*Right Middle*/
if(deg_test(180, start_angle, end_angle))
ver_line(center_x, center_y - r_out + 1, mask, thickness - 1, color, opa); /*Top Middle*/
ver_line(center_x, center_y - middle_r_out, mask, thickness, color, opa); /*Top Middle*/
if(deg_test(0, start_angle, end_angle))
ver_line(center_x, center_y + r_in, mask, thickness - 1, color, opa); /*Bottom middle*/
ver_line(center_x, center_y + r_in, mask, thickness, color, opa); /*Bottom middle*/
uint32_t r_out_sqr = r_out * r_out;
uint32_t r_in_sqr = r_in * r_in;
#if LV_ANTIALIAS
uint32_t r_out_aa_sqr = (r_out + 1) * (r_out + 1);
uint32_t r_in_aa_sqr = (r_in - 1) * (r_in - 1);
#endif
int16_t xi;
int16_t yi;
for(yi = -r_out; yi < 0; yi++) {
@@ -95,13 +109,56 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
x_end[1] = LV_COORD_MIN;
x_end[2] = LV_COORD_MIN;
x_end[3] = LV_COORD_MIN;
int xe = 0;
for(xi = -r_out; xi < 0; xi++) {
uint32_t r_act_sqr = xi * xi + yi * yi;
#if LV_ANTIALIAS
if(r_act_sqr > r_out_aa_sqr) {
continue;
}
#else
if(r_act_sqr > r_out_sqr) continue;
#endif
deg_base = fast_atan2(xi, yi) - 180;
#if LV_ANTIALIAS
int opa = -1;
if(r_act_sqr > r_out_sqr) {
opa = LV_OPA_100 * (r_out + 1) - lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr);
if(opa < LV_OPA_0)
opa = LV_OPA_0;
else if(opa > LV_OPA_100)
opa = LV_OPA_100;
} else if(r_act_sqr < r_in_sqr) {
if(xe == 0) xe = xi;
opa = lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr) - LV_OPA_100 * (r_in - 1);
if(opa < LV_OPA_0)
opa = LV_OPA_0;
else if(opa > LV_OPA_100)
opa = LV_OPA_100;
if(r_act_sqr < r_in_aa_sqr)
break; /*No need to continue the iteration in x once we found the inner edge of the
arc*/
}
if(opa != -1) {
if(deg_test(180 + deg_base, start_angle, end_angle)) {
lv_draw_px(center_x + xi, center_y + yi, mask, color, opa);
}
if(deg_test(360 - deg_base, start_angle, end_angle)) {
lv_draw_px(center_x + xi, center_y - yi, mask, color, opa);
}
if(deg_test(180 - deg_base, start_angle, end_angle)) {
lv_draw_px(center_x - xi, center_y + yi, mask, color, opa);
}
if(deg_test(deg_base, start_angle, end_angle)) {
lv_draw_px(center_x - xi, center_y - yi, mask, color, opa);
}
continue;
}
#endif
deg = 180 + deg_base;
if(deg_test(deg, start_angle, end_angle)) {
if(x_start[0] == LV_COORD_MIN) x_start[0] = xi;
@@ -130,35 +187,32 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
x_end[3] = xi - 1;
}
if(r_act_sqr < r_in_sqr)
if(r_act_sqr < r_in_sqr) {
xe = xi;
break; /*No need to continue the iteration in x once we found the inner edge of the
arc*/
}
}
if(x_start[0] != LV_COORD_MIN) {
if(x_end[0] == LV_COORD_MIN) x_end[0] = xi - 1;
if(x_end[0] == LV_COORD_MIN) x_end[0] = xe - 1;
hor_line(center_x + x_start[0], center_y + yi, mask, x_end[0] - x_start[0], color, opa);
}
if(x_start[1] != LV_COORD_MIN) {
if(x_end[1] == LV_COORD_MIN) x_end[1] = xi - 1;
if(x_end[1] == LV_COORD_MIN) x_end[1] = xe - 1;
hor_line(center_x + x_start[1], center_y - yi, mask, x_end[1] - x_start[1], color, opa);
}
if(x_start[2] != LV_COORD_MIN) {
if(x_end[2] == LV_COORD_MIN) x_end[2] = xi - 1;
if(x_end[2] == LV_COORD_MIN) x_end[2] = xe - 1;
hor_line(center_x - x_end[2], center_y + yi, mask, LV_MATH_ABS(x_end[2] - x_start[2]), color, opa);
}
if(x_start[3] != LV_COORD_MIN) {
if(x_end[3] == LV_COORD_MIN) x_end[3] = xi - 1;
if(x_end[3] == LV_COORD_MIN) x_end[3] = xe - 1;
hor_line(center_x - x_end[3], center_y - yi, mask, LV_MATH_ABS(x_end[3] - x_start[3]), color, opa);
}
#if LV_ANTIALIAS
/*TODO*/
#endif
}
}