Add arc antialiasing
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user