1 #include "lv_draw_dave2d.h"
2 #if LV_USE_DRAW_DAVE2D
3 
4 #include "../../../misc/lv_area_private.h"
5 
lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * u,const lv_draw_arc_dsc_t * dsc,const lv_area_t * coords)6 void lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * u, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords)
7 {
8 
9     uint32_t                flags = 0;
10     int32_t sin_start;
11     int32_t cos_start;
12     int32_t sin_end;
13     int32_t cos_end;
14     d2_s32 result;
15     lv_area_t clipped_area;
16     lv_area_t buffer_area;
17     lv_point_t arc_centre;
18     int32_t x;
19     int32_t y;
20 
21     if(!lv_area_intersect(&clipped_area, coords, u->base_unit.clip_area)) return;
22 
23     x = 0 - u->base_unit.target_layer->buf_area.x1;
24     y = 0 - u->base_unit.target_layer->buf_area.y1;
25 
26     buffer_area = u->base_unit.target_layer->buf_area;
27 
28     arc_centre = dsc->center;
29     arc_centre.x = arc_centre.x - buffer_area.x1;
30     arc_centre.y = arc_centre.y - buffer_area.y1;
31 
32     lv_area_move(&clipped_area, x, y);
33     lv_area_move(&buffer_area, x, y);
34 
35     //
36     // If both angles are equal (e.g. 0 and 0 or 180 and 180) nothing has to be done
37     //
38     if(dsc->start_angle == dsc->end_angle) {
39         return;                      // Nothing to do, no angle - no arc
40     }
41 
42 #if LV_USE_OS
43     lv_result_t  status;
44     status = lv_mutex_lock(u->pd2Mutex);
45     LV_ASSERT(LV_RESULT_OK == status);
46 #endif
47 
48 #if D2_RENDER_EACH_OPERATION
49     d2_selectrenderbuffer(u->d2_handle, u->renderbuffer);
50 #endif
51 
52     //
53     // Generate render operations
54     //
55     d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer);
56 
57     d2_setalpha(u->d2_handle, dsc->opa);
58 
59     d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color));
60 
61     result = d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2,
62                          (d2_border)clipped_area.y2);
63     LV_ASSERT(D2_OK == result);
64 
65     if(360 <= LV_ABS(dsc->start_angle - dsc->end_angle)) {
66         d2_rendercircle(u->d2_handle,
67                         (d2_point)D2_FIX4(arc_centre.x),
68                         (d2_point) D2_FIX4(arc_centre.y),
69                         (d2_width) D2_FIX4(dsc->radius - dsc->width / 2),
70                         (d2_width) D2_FIX4(dsc->width));
71     }
72     else { //An ARC, not a full circle
73         //
74         // If the difference between both is larger than 180 degrees we must use the concave flag
75         //
76         /** Set d2_wf_concave flag if the pie object to draw is concave shape. */
77         if((LV_ABS(dsc->start_angle - dsc->end_angle) > 180) || ((dsc->end_angle < dsc->start_angle) &&
78                                                                  (LV_ABS(dsc->start_angle - (dsc->end_angle + 360)) > 180))) {
79             flags = d2_wf_concave;
80         }
81         else {
82             flags = 0;
83         }
84 
85         sin_start = lv_trigo_sin((int16_t)dsc->start_angle);
86         cos_start = lv_trigo_cos((int16_t)dsc->start_angle);
87 
88         sin_end   = lv_trigo_sin((int16_t)dsc->end_angle);
89         cos_end   = lv_trigo_cos((int16_t)dsc->end_angle);
90 
91         bool draw_arc;
92         lv_area_t arc_area;
93         lv_area_t clip_arc;
94         lv_point_t start_point;
95         lv_point_t end_point;
96 
97         start_point.x = arc_centre.x + (int16_t)(((dsc->radius) * cos_start) >> LV_TRIGO_SHIFT);
98         start_point.y = arc_centre.y + (int16_t)(((dsc->radius) * sin_start) >> LV_TRIGO_SHIFT);
99 
100         end_point.x = arc_centre.x + (int16_t)(((dsc->radius) * cos_end) >> LV_TRIGO_SHIFT);
101         end_point.y = arc_centre.y + (int16_t)(((dsc->radius) * sin_end) >> LV_TRIGO_SHIFT);
102 
103         arc_area.x1 = LV_MIN3(start_point.x, end_point.x, arc_centre.x);
104         arc_area.y1 = LV_MIN3(start_point.y, end_point.y, arc_centre.y);
105 
106         arc_area.x2 = LV_MAX3(start_point.x, end_point.x, arc_centre.x);
107         arc_area.y2 = LV_MAX3(start_point.y, end_point.y, arc_centre.y);
108 
109         /* 0 degrees */
110         if((dsc->end_angle < dsc->start_angle) || ((dsc->start_angle < 360) && (dsc->end_angle > 360))) {
111             arc_area.x2 = arc_centre.x + dsc->radius;
112         }
113 
114         /* 90 degrees */
115         if(((dsc->end_angle > 90) && (dsc->start_angle < 90)) || ((dsc->start_angle < 90) &&
116                                                                   (dsc->end_angle < dsc->start_angle))) {
117             arc_area.y2 = arc_centre.y + dsc->radius;
118         }
119 
120         /* 180 degrees */
121         if(((dsc->end_angle > 180) && (dsc->start_angle < 180)) || ((dsc->start_angle < 180) &&
122                                                                     (dsc->end_angle < dsc->start_angle))) {
123             arc_area.x1 = arc_centre.x - dsc->radius;
124         }
125 
126         /* 270 degrees */
127         if(((dsc->end_angle > 270) && (dsc->start_angle < 270)) || ((dsc->start_angle < 270) &&
128                                                                     (dsc->end_angle < dsc->start_angle))) {
129             arc_area.y1 = arc_centre.y - dsc->radius;
130         }
131 
132         draw_arc = lv_area_intersect(&clip_arc, &arc_area, &clipped_area);
133 
134         if(draw_arc) {
135 
136             result = d2_renderwedge(u->d2_handle,
137                                     (d2_point)D2_FIX4(arc_centre.x),
138                                     (d2_point) D2_FIX4(arc_centre.y),
139                                     (d2_width) D2_FIX4(dsc->radius - dsc->width / 2),
140                                     (d2_width) D2_FIX4(dsc->width),
141                                     -(d2_s32)(sin_start << 1),
142                                     (d2_s32)(cos_start << 1),
143                                     (d2_s32)(sin_end << 1),
144                                     -(d2_s32)(cos_end << 1),
145                                     flags);
146             LV_ASSERT(D2_OK == result);
147 
148             if(dsc->rounded) {
149                 lv_point_t start_coord;
150                 lv_point_t end_coord;
151 
152                 start_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_start) >> LV_TRIGO_SHIFT);
153                 start_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_start) >> LV_TRIGO_SHIFT);
154 
155                 /** Render a circle. */
156                 d2_rendercircle(u->d2_handle,
157                                 (d2_point) D2_FIX4((uint16_t)(start_coord.x)),
158                                 (d2_point) D2_FIX4((uint16_t)(start_coord.y)),
159                                 (d2_width) D2_FIX4(dsc->width / 2), 0);
160 
161                 end_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_end) >> LV_TRIGO_SHIFT);
162                 end_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_end) >> LV_TRIGO_SHIFT);
163 
164                 /** Render a circle. */
165                 d2_rendercircle(u->d2_handle,
166                                 (d2_point) D2_FIX4((uint16_t)(end_coord.x)),
167                                 (d2_point) D2_FIX4((uint16_t)(end_coord.y)),
168                                 (d2_width) D2_FIX4(dsc->width / 2), 0);
169             }
170         }
171     }
172 
173     //
174     // Execute render operations
175     //
176 
177 #if D2_RENDER_EACH_OPERATION
178     d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0);
179     d2_flushframe(u->d2_handle);
180 #endif
181 
182 #if LV_USE_OS
183     status = lv_mutex_unlock(u->pd2Mutex);
184     LV_ASSERT(LV_RESULT_OK == status);
185 #endif
186 }
187 
188 #endif /*LV_USE_DRAW_DAVE2D*/
189