acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_draw_sw_arc.c (20946B)

      1 /**
      2  * @file lv_draw_arc.c
      3  *
      4  */
      5 
      6 /*********************
      7  *      INCLUDES
      8  *********************/
      9 #include "lv_draw_sw.h"
     10 #include "../../misc/lv_math.h"
     11 #include "../../misc/lv_log.h"
     12 #include "../../misc/lv_mem.h"
     13 #include "../lv_draw.h"
     14 
     15 /*********************
     16  *      DEFINES
     17  *********************/
     18 #define SPLIT_RADIUS_LIMIT 10  /*With radius greater than this the arc will drawn in quarters. A quarter is drawn only if there is arc in it*/
     19 #define SPLIT_ANGLE_GAP_LIMIT 60  /*With small gaps in the arc don't bother with splitting because there is nothing to skip.*/
     20 
     21 /**********************
     22  *      TYPEDEFS
     23  **********************/
     24 typedef struct {
     25     const lv_point_t * center;
     26     lv_coord_t radius;
     27     uint16_t start_angle;
     28     uint16_t end_angle;
     29     uint16_t start_quarter;
     30     uint16_t end_quarter;
     31     lv_coord_t width;
     32     lv_draw_rect_dsc_t * draw_dsc;
     33     const lv_area_t * draw_area;
     34     lv_draw_ctx_t * draw_ctx;
     35 } quarter_draw_dsc_t;
     36 
     37 /**********************
     38  *  STATIC PROTOTYPES
     39  **********************/
     40 #if LV_DRAW_COMPLEX
     41     static void draw_quarter_0(quarter_draw_dsc_t * q);
     42     static void draw_quarter_1(quarter_draw_dsc_t * q);
     43     static void draw_quarter_2(quarter_draw_dsc_t * q);
     44     static void draw_quarter_3(quarter_draw_dsc_t * q);
     45     static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area);
     46 #endif /*LV_DRAW_COMPLEX*/
     47 
     48 /**********************
     49  *  STATIC VARIABLES
     50  **********************/
     51 
     52 /**********************
     53  *      MACROS
     54  **********************/
     55 
     56 /**********************
     57  *   GLOBAL FUNCTIONS
     58  **********************/
     59 
     60 void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius,
     61                     uint16_t start_angle, uint16_t end_angle)
     62 {
     63 #if LV_DRAW_COMPLEX
     64     if(dsc->opa <= LV_OPA_MIN) return;
     65     if(dsc->width == 0) return;
     66     if(start_angle == end_angle) return;
     67 
     68     lv_coord_t width = dsc->width;
     69     if(width > radius) width = radius;
     70 
     71     lv_draw_rect_dsc_t cir_dsc;
     72     lv_draw_rect_dsc_init(&cir_dsc);
     73     cir_dsc.blend_mode = dsc->blend_mode;
     74     if(dsc->img_src) {
     75         cir_dsc.bg_opa = LV_OPA_TRANSP;
     76         cir_dsc.bg_img_src = dsc->img_src;
     77         cir_dsc.bg_img_opa = dsc->opa;
     78     }
     79     else {
     80         cir_dsc.bg_opa = dsc->opa;
     81         cir_dsc.bg_color = dsc->color;
     82     }
     83 
     84     lv_area_t area_out;
     85     area_out.x1 = center->x - radius;
     86     area_out.y1 = center->y - radius;
     87     area_out.x2 = center->x + radius - 1;  /*-1 because the center already belongs to the left/bottom part*/
     88     area_out.y2 = center->y + radius - 1;
     89 
     90     lv_area_t area_in;
     91     lv_area_copy(&area_in, &area_out);
     92     area_in.x1 += dsc->width;
     93     area_in.y1 += dsc->width;
     94     area_in.x2 -= dsc->width;
     95     area_in.y2 -= dsc->width;
     96 
     97     /*Create inner the mask*/
     98     int16_t mask_in_id = LV_MASK_ID_INV;
     99     lv_draw_mask_radius_param_t mask_in_param;
    100     if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
    101         lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
    102         mask_in_id = lv_draw_mask_add(&mask_in_param, NULL);
    103     }
    104 
    105     lv_draw_mask_radius_param_t mask_out_param;
    106     lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
    107     int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL);
    108 
    109     /*Draw a full ring*/
    110     if(start_angle + 360 == end_angle || start_angle == end_angle + 360) {
    111         cir_dsc.radius = LV_RADIUS_CIRCLE;
    112         lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
    113 
    114         lv_draw_mask_remove_id(mask_out_id);
    115         if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
    116 
    117         lv_draw_mask_free_param(&mask_out_param);
    118         lv_draw_mask_free_param(&mask_in_param);
    119 
    120         return;
    121     }
    122 
    123     while(start_angle >= 360) start_angle -= 360;
    124     while(end_angle >= 360) end_angle -= 360;
    125 
    126     lv_draw_mask_angle_param_t mask_angle_param;
    127     lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
    128     int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL);
    129 
    130     int32_t angle_gap;
    131     if(end_angle > start_angle) {
    132         angle_gap = 360 - (end_angle - start_angle);
    133     }
    134     else {
    135         angle_gap = start_angle - end_angle;
    136     }
    137 
    138     const lv_area_t * clip_area_ori = draw_ctx->clip_area;
    139 
    140     if(angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) {
    141         /*Handle each quarter individually and skip which is empty*/
    142         quarter_draw_dsc_t q_dsc;
    143         q_dsc.center = center;
    144         q_dsc.radius = radius;
    145         q_dsc.start_angle = start_angle;
    146         q_dsc.end_angle = end_angle;
    147         q_dsc.start_quarter = (start_angle / 90) & 0x3;
    148         q_dsc.end_quarter = (end_angle / 90) & 0x3;
    149         q_dsc.width = width;
    150         q_dsc.draw_dsc = &cir_dsc;
    151         q_dsc.draw_area = &area_out;
    152         q_dsc.draw_ctx = draw_ctx;
    153 
    154         draw_quarter_0(&q_dsc);
    155         draw_quarter_1(&q_dsc);
    156         draw_quarter_2(&q_dsc);
    157         draw_quarter_3(&q_dsc);
    158     }
    159     else {
    160         lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
    161     }
    162 
    163     lv_draw_mask_free_param(&mask_angle_param);
    164     lv_draw_mask_free_param(&mask_out_param);
    165     lv_draw_mask_free_param(&mask_in_param);
    166 
    167     lv_draw_mask_remove_id(mask_angle_id);
    168     lv_draw_mask_remove_id(mask_out_id);
    169     if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
    170 
    171     if(dsc->rounded) {
    172 
    173         lv_draw_mask_radius_param_t mask_end_param;
    174 
    175         lv_area_t round_area;
    176         get_rounded_area(start_angle, radius, width, &round_area);
    177         round_area.x1 += center->x;
    178         round_area.x2 += center->x;
    179         round_area.y1 += center->y;
    180         round_area.y2 += center->y;
    181         lv_area_t clip_area2;
    182         if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
    183             lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
    184             int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
    185 
    186             draw_ctx->clip_area = &clip_area2;
    187             lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
    188             lv_draw_mask_remove_id(mask_end_id);
    189             lv_draw_mask_free_param(&mask_end_param);
    190         }
    191 
    192         get_rounded_area(end_angle, radius, width, &round_area);
    193         round_area.x1 += center->x;
    194         round_area.x2 += center->x;
    195         round_area.y1 += center->y;
    196         round_area.y2 += center->y;
    197         if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
    198             lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
    199             int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
    200 
    201             draw_ctx->clip_area = &clip_area2;
    202             lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
    203             lv_draw_mask_remove_id(mask_end_id);
    204             lv_draw_mask_free_param(&mask_end_param);
    205         }
    206         draw_ctx->clip_area = clip_area_ori;
    207     }
    208 #else
    209     LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0");
    210     LV_UNUSED(center);
    211     LV_UNUSED(radius);
    212     LV_UNUSED(start_angle);
    213     LV_UNUSED(end_angle);
    214     LV_UNUSED(draw_ctx);
    215     LV_UNUSED(dsc);
    216 #endif /*LV_DRAW_COMPLEX*/
    217 }
    218 
    219 /**********************
    220  *   STATIC FUNCTIONS
    221  **********************/
    222 
    223 #if LV_DRAW_COMPLEX
    224 static void draw_quarter_0(quarter_draw_dsc_t * q)
    225 {
    226     const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
    227     lv_area_t quarter_area;
    228 
    229     if(q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) {
    230         /*Small arc here*/
    231         quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    232         quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    233 
    234         quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
    235         quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    236 
    237         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    238         if(ok) {
    239             q->draw_ctx->clip_area = &quarter_area;
    240             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    241         }
    242     }
    243     else if(q->start_quarter == 0 || q->end_quarter == 0) {
    244         /*Start and/or end arcs here*/
    245         if(q->start_quarter == 0) {
    246             quarter_area.x1 = q->center->x;
    247             quarter_area.y2 = q->center->y + q->radius;
    248 
    249             quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    250             quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    251 
    252             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    253             if(ok) {
    254                 q->draw_ctx->clip_area = &quarter_area;
    255                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    256             }
    257         }
    258         if(q->end_quarter == 0) {
    259             quarter_area.x2 = q->center->x + q->radius;
    260             quarter_area.y1 = q->center->y;
    261 
    262             quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
    263             quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    264 
    265             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    266             if(ok) {
    267                 q->draw_ctx->clip_area = &quarter_area;
    268                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    269             }
    270         }
    271     }
    272     else if((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) ||
    273             (q->start_quarter == 2 && q->end_quarter == 1) ||
    274             (q->start_quarter == 3 && q->end_quarter == 2) ||
    275             (q->start_quarter == 3 && q->end_quarter == 1)) {
    276         /*Arc crosses here*/
    277         quarter_area.x1 = q->center->x;
    278         quarter_area.y1 = q->center->y;
    279         quarter_area.x2 = q->center->x + q->radius;
    280         quarter_area.y2 = q->center->y + q->radius;
    281 
    282         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    283         if(ok) {
    284             q->draw_ctx->clip_area = &quarter_area;
    285             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    286         }
    287     }
    288     q->draw_ctx->clip_area = clip_area_ori;
    289 }
    290 
    291 static void draw_quarter_1(quarter_draw_dsc_t * q)
    292 {
    293     const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
    294     lv_area_t quarter_area;
    295 
    296     if(q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) {
    297         /*Small arc here*/
    298         quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
    299         quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    300 
    301         quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    302         quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    303 
    304         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    305         if(ok) {
    306             q->draw_ctx->clip_area = &quarter_area;
    307             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    308         }
    309     }
    310     else if(q->start_quarter == 1 || q->end_quarter == 1) {
    311         /*Start and/or end arcs here*/
    312         if(q->start_quarter == 1) {
    313             quarter_area.x1 = q->center->x - q->radius;
    314             quarter_area.y1 = q->center->y;
    315 
    316             quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
    317             quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    318 
    319             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    320             if(ok) {
    321                 q->draw_ctx->clip_area = &quarter_area;
    322                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    323             }
    324         }
    325         if(q->end_quarter == 1) {
    326             quarter_area.x2 = q->center->x - 1;
    327             quarter_area.y2 = q->center->y + q->radius;
    328 
    329             quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    330             quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    331 
    332             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    333             if(ok) {
    334                 q->draw_ctx->clip_area = &quarter_area;
    335                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    336             }
    337         }
    338     }
    339     else if((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) ||
    340             (q->start_quarter == 0 && q->end_quarter == 2) ||
    341             (q->start_quarter == 0 && q->end_quarter == 3) ||
    342             (q->start_quarter == 3 && q->end_quarter == 2)) {
    343         /*Arc crosses here*/
    344         quarter_area.x1 = q->center->x - q->radius;
    345         quarter_area.y1 = q->center->y;
    346         quarter_area.x2 = q->center->x - 1;
    347         quarter_area.y2 = q->center->y + q->radius;
    348 
    349         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    350         if(ok) {
    351             q->draw_ctx->clip_area = &quarter_area;
    352             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    353         }
    354     }
    355     q->draw_ctx->clip_area = clip_area_ori;
    356 }
    357 
    358 static void draw_quarter_2(quarter_draw_dsc_t * q)
    359 {
    360     const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
    361     lv_area_t quarter_area;
    362 
    363     if(q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) {
    364         /*Small arc here*/
    365         quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    366         quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    367 
    368         quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
    369         quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    370 
    371         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    372         if(ok) {
    373             q->draw_ctx->clip_area = &quarter_area;
    374             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    375         }
    376     }
    377     else if(q->start_quarter == 2 || q->end_quarter == 2) {
    378         /*Start and/or end arcs here*/
    379         if(q->start_quarter == 2) {
    380             quarter_area.x2 = q->center->x - 1;
    381             quarter_area.y1 = q->center->y - q->radius;
    382 
    383             quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    384             quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    385 
    386             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    387             if(ok) {
    388                 q->draw_ctx->clip_area = &quarter_area;
    389                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    390             }
    391         }
    392         if(q->end_quarter == 2) {
    393             quarter_area.x1 = q->center->x - q->radius;
    394             quarter_area.y2 = q->center->y - 1;
    395 
    396             quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    397             quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
    398 
    399             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    400             if(ok) {
    401                 q->draw_ctx->clip_area = &quarter_area;
    402                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    403             }
    404         }
    405     }
    406     else if((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) ||
    407             (q->start_quarter == 0 && q->end_quarter == 3) ||
    408             (q->start_quarter == 1 && q->end_quarter == 3) ||
    409             (q->start_quarter == 1 && q->end_quarter == 0)) {
    410         /*Arc crosses here*/
    411         quarter_area.x1 = q->center->x - q->radius;
    412         quarter_area.y1 = q->center->y - q->radius;
    413         quarter_area.x2 = q->center->x - 1;
    414         quarter_area.y2 = q->center->y - 1;
    415 
    416         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    417         if(ok) {
    418             q->draw_ctx->clip_area = &quarter_area;
    419             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    420         }
    421     }
    422     q->draw_ctx->clip_area = clip_area_ori;
    423 }
    424 
    425 static void draw_quarter_3(quarter_draw_dsc_t * q)
    426 {
    427     const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
    428     lv_area_t quarter_area;
    429 
    430     if(q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) {
    431         /*Small arc here*/
    432         quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    433         quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
    434 
    435         quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    436         quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    437 
    438         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    439         if(ok) {
    440             q->draw_ctx->clip_area = &quarter_area;
    441             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    442         }
    443     }
    444     else if(q->start_quarter == 3 || q->end_quarter == 3) {
    445         /*Start and/or end arcs here*/
    446         if(q->start_quarter == 3) {
    447             quarter_area.x2 = q->center->x + q->radius;
    448             quarter_area.y2 = q->center->y - 1;
    449 
    450             quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    451             quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
    452 
    453             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    454             if(ok) {
    455                 q->draw_ctx->clip_area = &quarter_area;
    456                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    457             }
    458         }
    459         if(q->end_quarter == 3) {
    460             quarter_area.x1 = q->center->x;
    461             quarter_area.y1 = q->center->y - q->radius;
    462 
    463             quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
    464             quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
    465 
    466             bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    467             if(ok) {
    468                 q->draw_ctx->clip_area = &quarter_area;
    469                 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    470             }
    471         }
    472     }
    473     else if((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) ||
    474             (q->start_quarter == 2 && q->end_quarter == 0) ||
    475             (q->start_quarter == 1 && q->end_quarter == 0) ||
    476             (q->start_quarter == 2 && q->end_quarter == 1)) {
    477         /*Arc crosses here*/
    478         quarter_area.x1 = q->center->x;
    479         quarter_area.y1 = q->center->y - q->radius;
    480         quarter_area.x2 = q->center->x + q->radius;
    481         quarter_area.y2 = q->center->y - 1;
    482 
    483         bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
    484         if(ok) {
    485             q->draw_ctx->clip_area = &quarter_area;
    486             lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
    487         }
    488     }
    489 
    490     q->draw_ctx->clip_area = clip_area_ori;
    491 }
    492 
    493 static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area)
    494 {
    495     const uint8_t ps = 8;
    496     const uint8_t pa = 127;
    497 
    498     int32_t thick_half = thickness / 2;
    499     uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
    500 
    501     int32_t cir_x;
    502     int32_t cir_y;
    503 
    504     cir_x = ((radius - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps);
    505     cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
    506 
    507     /*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
    508     if(cir_x > 0) {
    509         cir_x = (cir_x - pa) >> ps;
    510         res_area->x1 = cir_x - thick_half + thick_corr;
    511         res_area->x2 = cir_x + thick_half;
    512     }
    513     else {
    514         cir_x = (cir_x + pa) >> ps;
    515         res_area->x1 = cir_x - thick_half;
    516         res_area->x2 = cir_x + thick_half - thick_corr;
    517     }
    518 
    519     if(cir_y > 0) {
    520         cir_y = (cir_y - pa) >> ps;
    521         res_area->y1 = cir_y - thick_half + thick_corr;
    522         res_area->y2 = cir_y + thick_half;
    523     }
    524     else {
    525         cir_y = (cir_y + pa) >> ps;
    526         res_area->y1 = cir_y - thick_half;
    527         res_area->y2 = cir_y + thick_half - thick_corr;
    528     }
    529 }
    530 
    531 #endif /*LV_DRAW_COMPLEX*/