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
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,uint16_t start_angle,uint16_t end_angle)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 bool mask_in_param_valid = false;
101 if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
102 lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
103 mask_in_param_valid = true;
104 mask_in_id = lv_draw_mask_add(&mask_in_param, NULL);
105 }
106
107 lv_draw_mask_radius_param_t mask_out_param;
108 lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
109 int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL);
110
111 /*Draw a full ring*/
112 if(start_angle + 360 == end_angle || start_angle == end_angle + 360) {
113 cir_dsc.radius = LV_RADIUS_CIRCLE;
114 lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
115
116 lv_draw_mask_remove_id(mask_out_id);
117 if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
118
119 lv_draw_mask_free_param(&mask_out_param);
120 if(mask_in_param_valid) {
121 lv_draw_mask_free_param(&mask_in_param);
122 }
123
124 return;
125 }
126
127 while(start_angle >= 360) start_angle -= 360;
128 while(end_angle >= 360) end_angle -= 360;
129
130 lv_draw_mask_angle_param_t mask_angle_param;
131 lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle);
132 int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL);
133
134 int32_t angle_gap;
135 if(end_angle > start_angle) {
136 angle_gap = 360 - (end_angle - start_angle);
137 }
138 else {
139 angle_gap = start_angle - end_angle;
140 }
141
142 const lv_area_t * clip_area_ori = draw_ctx->clip_area;
143
144 if(angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) {
145 /*Handle each quarter individually and skip which is empty*/
146 quarter_draw_dsc_t q_dsc;
147 q_dsc.center = center;
148 q_dsc.radius = radius;
149 q_dsc.start_angle = start_angle;
150 q_dsc.end_angle = end_angle;
151 q_dsc.start_quarter = (start_angle / 90) & 0x3;
152 q_dsc.end_quarter = (end_angle / 90) & 0x3;
153 q_dsc.width = width;
154 q_dsc.draw_dsc = &cir_dsc;
155 q_dsc.draw_area = &area_out;
156 q_dsc.draw_ctx = draw_ctx;
157
158 draw_quarter_0(&q_dsc);
159 draw_quarter_1(&q_dsc);
160 draw_quarter_2(&q_dsc);
161 draw_quarter_3(&q_dsc);
162 }
163 else {
164 lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
165 }
166
167 lv_draw_mask_free_param(&mask_angle_param);
168 lv_draw_mask_free_param(&mask_out_param);
169 if(mask_in_param_valid) {
170 lv_draw_mask_free_param(&mask_in_param);
171 }
172
173 lv_draw_mask_remove_id(mask_angle_id);
174 lv_draw_mask_remove_id(mask_out_id);
175 if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
176
177 if(dsc->rounded) {
178
179 lv_draw_mask_radius_param_t mask_end_param;
180
181 lv_area_t round_area;
182 get_rounded_area(start_angle, radius, width, &round_area);
183 round_area.x1 += center->x;
184 round_area.x2 += center->x;
185 round_area.y1 += center->y;
186 round_area.y2 += center->y;
187 lv_area_t clip_area2;
188 if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
189 lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
190 int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
191
192 draw_ctx->clip_area = &clip_area2;
193 lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
194 lv_draw_mask_remove_id(mask_end_id);
195 lv_draw_mask_free_param(&mask_end_param);
196 }
197
198 get_rounded_area(end_angle, radius, width, &round_area);
199 round_area.x1 += center->x;
200 round_area.x2 += center->x;
201 round_area.y1 += center->y;
202 round_area.y2 += center->y;
203 if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) {
204 lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
205 int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
206
207 draw_ctx->clip_area = &clip_area2;
208 lv_draw_rect(draw_ctx, &cir_dsc, &area_out);
209 lv_draw_mask_remove_id(mask_end_id);
210 lv_draw_mask_free_param(&mask_end_param);
211 }
212 draw_ctx->clip_area = clip_area_ori;
213 }
214 #else
215 LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0");
216 LV_UNUSED(center);
217 LV_UNUSED(radius);
218 LV_UNUSED(start_angle);
219 LV_UNUSED(end_angle);
220 LV_UNUSED(draw_ctx);
221 LV_UNUSED(dsc);
222 #endif /*LV_DRAW_COMPLEX*/
223 }
224
225 /**********************
226 * STATIC FUNCTIONS
227 **********************/
228
229 #if LV_DRAW_COMPLEX
draw_quarter_0(quarter_draw_dsc_t * q)230 static void draw_quarter_0(quarter_draw_dsc_t * q)
231 {
232 const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
233 lv_area_t quarter_area;
234
235 if(q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) {
236 /*Small arc here*/
237 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
238 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
239
240 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
241 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
242
243 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
244 if(ok) {
245 q->draw_ctx->clip_area = &quarter_area;
246 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
247 }
248 }
249 else if(q->start_quarter == 0 || q->end_quarter == 0) {
250 /*Start and/or end arcs here*/
251 if(q->start_quarter == 0) {
252 quarter_area.x1 = q->center->x;
253 quarter_area.y2 = q->center->y + q->radius;
254
255 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
256 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
257
258 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
259 if(ok) {
260 q->draw_ctx->clip_area = &quarter_area;
261 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
262 }
263 }
264 if(q->end_quarter == 0) {
265 quarter_area.x2 = q->center->x + q->radius;
266 quarter_area.y1 = q->center->y;
267
268 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
269 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
270
271 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
272 if(ok) {
273 q->draw_ctx->clip_area = &quarter_area;
274 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
275 }
276 }
277 }
278 else if((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) ||
279 (q->start_quarter == 2 && q->end_quarter == 1) ||
280 (q->start_quarter == 3 && q->end_quarter == 2) ||
281 (q->start_quarter == 3 && q->end_quarter == 1)) {
282 /*Arc crosses here*/
283 quarter_area.x1 = q->center->x;
284 quarter_area.y1 = q->center->y;
285 quarter_area.x2 = q->center->x + q->radius;
286 quarter_area.y2 = q->center->y + q->radius;
287
288 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
289 if(ok) {
290 q->draw_ctx->clip_area = &quarter_area;
291 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
292 }
293 }
294 q->draw_ctx->clip_area = clip_area_ori;
295 }
296
draw_quarter_1(quarter_draw_dsc_t * q)297 static void draw_quarter_1(quarter_draw_dsc_t * q)
298 {
299 const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
300 lv_area_t quarter_area;
301
302 if(q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) {
303 /*Small arc here*/
304 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
305 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
306
307 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
308 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
309
310 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
311 if(ok) {
312 q->draw_ctx->clip_area = &quarter_area;
313 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
314 }
315 }
316 else if(q->start_quarter == 1 || q->end_quarter == 1) {
317 /*Start and/or end arcs here*/
318 if(q->start_quarter == 1) {
319 quarter_area.x1 = q->center->x - q->radius;
320 quarter_area.y1 = q->center->y;
321
322 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
323 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
324
325 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
326 if(ok) {
327 q->draw_ctx->clip_area = &quarter_area;
328 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
329 }
330 }
331 if(q->end_quarter == 1) {
332 quarter_area.x2 = q->center->x - 1;
333 quarter_area.y2 = q->center->y + q->radius;
334
335 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
336 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
337
338 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
339 if(ok) {
340 q->draw_ctx->clip_area = &quarter_area;
341 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
342 }
343 }
344 }
345 else if((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) ||
346 (q->start_quarter == 0 && q->end_quarter == 2) ||
347 (q->start_quarter == 0 && q->end_quarter == 3) ||
348 (q->start_quarter == 3 && q->end_quarter == 2)) {
349 /*Arc crosses here*/
350 quarter_area.x1 = q->center->x - q->radius;
351 quarter_area.y1 = q->center->y;
352 quarter_area.x2 = q->center->x - 1;
353 quarter_area.y2 = q->center->y + q->radius;
354
355 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
356 if(ok) {
357 q->draw_ctx->clip_area = &quarter_area;
358 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
359 }
360 }
361 q->draw_ctx->clip_area = clip_area_ori;
362 }
363
draw_quarter_2(quarter_draw_dsc_t * q)364 static void draw_quarter_2(quarter_draw_dsc_t * q)
365 {
366 const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
367 lv_area_t quarter_area;
368
369 if(q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) {
370 /*Small arc here*/
371 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
372 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
373
374 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
375 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
376
377 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
378 if(ok) {
379 q->draw_ctx->clip_area = &quarter_area;
380 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
381 }
382 }
383 else if(q->start_quarter == 2 || q->end_quarter == 2) {
384 /*Start and/or end arcs here*/
385 if(q->start_quarter == 2) {
386 quarter_area.x2 = q->center->x - 1;
387 quarter_area.y1 = q->center->y - q->radius;
388
389 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
390 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
391
392 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
393 if(ok) {
394 q->draw_ctx->clip_area = &quarter_area;
395 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
396 }
397 }
398 if(q->end_quarter == 2) {
399 quarter_area.x1 = q->center->x - q->radius;
400 quarter_area.y2 = q->center->y - 1;
401
402 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
403 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
404
405 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
406 if(ok) {
407 q->draw_ctx->clip_area = &quarter_area;
408 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
409 }
410 }
411 }
412 else if((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) ||
413 (q->start_quarter == 0 && q->end_quarter == 3) ||
414 (q->start_quarter == 1 && q->end_quarter == 3) ||
415 (q->start_quarter == 1 && q->end_quarter == 0)) {
416 /*Arc crosses here*/
417 quarter_area.x1 = q->center->x - q->radius;
418 quarter_area.y1 = q->center->y - q->radius;
419 quarter_area.x2 = q->center->x - 1;
420 quarter_area.y2 = q->center->y - 1;
421
422 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
423 if(ok) {
424 q->draw_ctx->clip_area = &quarter_area;
425 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
426 }
427 }
428 q->draw_ctx->clip_area = clip_area_ori;
429 }
430
draw_quarter_3(quarter_draw_dsc_t * q)431 static void draw_quarter_3(quarter_draw_dsc_t * q)
432 {
433 const lv_area_t * clip_area_ori = q->draw_ctx->clip_area;
434 lv_area_t quarter_area;
435
436 if(q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) {
437 /*Small arc here*/
438 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
439 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
440
441 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
442 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
443
444 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
445 if(ok) {
446 q->draw_ctx->clip_area = &quarter_area;
447 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
448 }
449 }
450 else if(q->start_quarter == 3 || q->end_quarter == 3) {
451 /*Start and/or end arcs here*/
452 if(q->start_quarter == 3) {
453 quarter_area.x2 = q->center->x + q->radius;
454 quarter_area.y2 = q->center->y - 1;
455
456 quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
457 quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
458
459 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
460 if(ok) {
461 q->draw_ctx->clip_area = &quarter_area;
462 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
463 }
464 }
465 if(q->end_quarter == 3) {
466 quarter_area.x1 = q->center->x;
467 quarter_area.y1 = q->center->y - q->radius;
468
469 quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
470 quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
471
472 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
473 if(ok) {
474 q->draw_ctx->clip_area = &quarter_area;
475 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
476 }
477 }
478 }
479 else if((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) ||
480 (q->start_quarter == 2 && q->end_quarter == 0) ||
481 (q->start_quarter == 1 && q->end_quarter == 0) ||
482 (q->start_quarter == 2 && q->end_quarter == 1)) {
483 /*Arc crosses here*/
484 quarter_area.x1 = q->center->x;
485 quarter_area.y1 = q->center->y - q->radius;
486 quarter_area.x2 = q->center->x + q->radius;
487 quarter_area.y2 = q->center->y - 1;
488
489 bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori);
490 if(ok) {
491 q->draw_ctx->clip_area = &quarter_area;
492 lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area);
493 }
494 }
495
496 q->draw_ctx->clip_area = clip_area_ori;
497 }
498
get_rounded_area(int16_t angle,lv_coord_t radius,uint8_t thickness,lv_area_t * res_area)499 static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area)
500 {
501 const uint8_t ps = 8;
502 const uint8_t pa = 127;
503
504 int32_t thick_half = thickness / 2;
505 uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
506
507 int32_t cir_x;
508 int32_t cir_y;
509
510 cir_x = ((radius - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps);
511 cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
512
513 /*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
514 if(cir_x > 0) {
515 cir_x = (cir_x - pa) >> ps;
516 res_area->x1 = cir_x - thick_half + thick_corr;
517 res_area->x2 = cir_x + thick_half;
518 }
519 else {
520 cir_x = (cir_x + pa) >> ps;
521 res_area->x1 = cir_x - thick_half;
522 res_area->x2 = cir_x + thick_half - thick_corr;
523 }
524
525 if(cir_y > 0) {
526 cir_y = (cir_y - pa) >> ps;
527 res_area->y1 = cir_y - thick_half + thick_corr;
528 res_area->y2 = cir_y + thick_half;
529 }
530 else {
531 cir_y = (cir_y + pa) >> ps;
532 res_area->y1 = cir_y - thick_half;
533 res_area->y2 = cir_y + thick_half - thick_corr;
534 }
535 }
536
537 #endif /*LV_DRAW_COMPLEX*/
538