1 #include "lv_draw_dave2d.h"
2 #if LV_USE_DRAW_DAVE2D
3 
4 #include "../../../misc/lv_area_private.h"
5 
lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * u,const lv_draw_fill_dsc_t * dsc,const lv_area_t * coords)6 void lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * u, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords)
7 {
8     lv_area_t draw_area;
9     lv_area_t coordinates;
10     bool is_common;
11     int32_t x;
12     int32_t y;
13     d2_u8 current_alpha_mode = 0;
14     d2_s32 result;
15     d2_u32 flags = 0;
16 
17     lv_point_t arc_centre;
18 
19     is_common = lv_area_intersect(&draw_area, coords, u->base_unit.clip_area);
20     if(!is_common) return;
21 
22 #if LV_USE_OS
23     lv_result_t  status;
24     status = lv_mutex_lock(u->pd2Mutex);
25     LV_ASSERT(LV_RESULT_OK == status);
26 #endif
27 
28     lv_area_copy(&coordinates, coords);
29 
30     x = 0 - u->base_unit.target_layer->buf_area.x1;
31     y = 0 - u->base_unit.target_layer->buf_area.y1;
32 
33     lv_area_move(&draw_area, x, y);
34     lv_area_move(&coordinates, x, y);
35 
36     //
37     // Generate render operations
38     //
39 #if D2_RENDER_EACH_OPERATION
40     d2_selectrenderbuffer(u->d2_handle, u->renderbuffer);
41 #endif
42 
43     d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer);
44 
45     if(LV_GRAD_DIR_NONE != dsc->grad.dir) {
46         float a1;
47         float a2;
48 
49         float y1;
50         float y2;
51 
52         float y3;
53         float y0;
54         int16_t y0_i ;
55         int16_t y3_i ;
56 
57         if(LV_GRAD_DIR_VER == dsc->grad.dir) {
58             a1 = dsc->grad.stops[0].opa;
59             a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa;
60 
61             y1 = (float)LV_MIN(coordinates.y1, coordinates.y2);
62             y2 = (float)LV_MAX(coordinates.y1, coordinates.y2);
63 
64             if(a1 < a2) {
65                 /* TODO */
66                 LV_ASSERT(0);
67                 y0 = 0.0f;//silence the compiler warning
68                 y3 = 0.0f;
69 
70             }
71             else {
72                 y0 = y2 - ((y2 - y1) / (a2 - a1) * (a2)); //point where alpha is 0
73                 y3 = y1 + ((y2 - y1) / (a2 - a1) * (255 - a1)); //point where alpha is 255
74             }
75 
76             y0_i = (int16_t)y0;
77             y3_i = (int16_t)y3;
78 
79             d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(y0_i), (d2_point)D2_FIX4(0),
80                                 (d2_point)D2_FIX4((y3_i - y0_i)));
81         }
82         else if(LV_GRAD_DIR_HOR == dsc->grad.dir) {
83             /* TODO */
84             LV_ASSERT(0);
85 
86             float x1;
87             float x2;
88 
89             float x3;
90             float x0;
91             int16_t x0_i ;
92             int16_t x3_i ;
93 
94             a1 = dsc->grad.stops[0].opa;
95             a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa;
96 
97             x1 = (float)LV_MIN(coordinates.x1, coordinates.x2);
98             x2 = (float)LV_MAX(coordinates.x1, coordinates.x2);
99 
100             if(a1 < a2) {
101                 /* TODO */
102                 LV_ASSERT(0);
103                 x0 = 0.0f;//silence the compiler warning
104                 x3 = 0.0f;
105 
106             }
107             else {
108                 x0 = x2 - ((x2 - x1) / (a2 - a1) * (a2)); //point where alpha is 0
109                 x3 = x1 + ((x2 - x1) / (a2 - a1) * (255 - a1)); //point where alpha is 255
110             }
111 
112             x0_i = (int16_t)x0;
113             x3_i = (int16_t)x3;
114 
115             d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(x0_i), (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(x3_i - x0_i),
116                                 (d2_point)D2_FIX4((0)));
117         }
118 
119         current_alpha_mode = d2_getalphamode(u->d2_handle);
120         d2_setfillmode(u->d2_handle, d2_fm_color);
121         d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->grad.stops[0].color));
122         d2_setalphamode(u->d2_handle, d2_am_gradient1);
123     }
124     else {
125         d2_setfillmode(u->d2_handle, d2_fm_color); //default
126         d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color));
127         d2_setalpha(u->d2_handle, dsc->opa);
128     }
129 
130     d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2,
131                 (d2_border)draw_area.y2);
132 
133     if(dsc->radius == 0) {
134 
135         d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(coordinates.x1),
136                      (d2_point)D2_FIX4(coordinates.y1),
137                      (d2_point)D2_FIX4(lv_area_get_width(&coordinates)),
138                      (d2_point)D2_FIX4(lv_area_get_height(&coordinates)));
139     }
140     else {
141         /*Get the real radius. Can't be larger than the half of the shortest side */
142         int32_t coords_bg_w = lv_area_get_width(&coordinates);
143         int32_t coords_bg_h = lv_area_get_height(&coordinates);
144         int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h);
145         int32_t radius = LV_MIN(dsc->radius, short_side >> 1);
146 
147         arc_centre.x = coordinates.x1 + radius;
148         arc_centre.y = coordinates.y1 + radius;
149 
150         if(((2 * radius) == coords_bg_w)  && ((2 * radius) == coords_bg_h)) {
151             result = d2_rendercircle(u->d2_handle,
152                                      (d2_point)D2_FIX4(arc_centre.x),
153                                      (d2_point) D2_FIX4(arc_centre.y),
154                                      (d2_width) D2_FIX4(radius),
155                                      (d2_width) D2_FIX4(0));
156             LV_ASSERT(D2_OK == result);
157         }
158         else {
159 
160             lv_area_t arc_area;
161             lv_area_t clip_arc;
162             arc_centre.x = coordinates.x1 + radius;
163             arc_centre.y = coordinates.y1 + radius;
164 
165             arc_area.x1 = coordinates.x1;
166             arc_area.y1 = coordinates.y1;
167             arc_area.x2 = coordinates.x1 + radius;
168             arc_area.y2 = coordinates.y1 + radius;
169 
170             if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
171 
172                 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
173                             (d2_border)clip_arc.y2);
174 
175                 // d2_renderwedge internally changes the clip rectangle, only draw it if it is in side the current clip rectangle
176                 result = d2_renderwedge(u->d2_handle,
177                                         (d2_point)D2_FIX4(arc_centre.x),
178                                         (d2_point) D2_FIX4(arc_centre.y),
179                                         (d2_width) D2_FIX4(radius),
180                                         (d2_width) D2_FIX4(0),
181                                         (d2_s32) D2_FIX16(0), // 180 Degrees
182                                         (d2_s32)  D2_FIX16((int16_t) -1),
183                                         (d2_s32)  D2_FIX16((int16_t) -1),//( 270 Degrees
184                                         (d2_s32) D2_FIX16(0),
185                                         flags);
186                 LV_ASSERT(D2_OK == result);
187             }
188 
189             arc_centre.x = coordinates.x2 - radius;
190             arc_centre.y = coordinates.y1 + radius;
191 
192             arc_area.x1 = coordinates.x2 - radius;
193             arc_area.y1 = coordinates.y1;
194             arc_area.x2 = coordinates.x2;
195             arc_area.y2 = coordinates.y1 + radius;
196 
197             if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
198                 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
199                             (d2_border)clip_arc.y2);
200 
201                 result = d2_renderwedge(u->d2_handle,
202                                         (d2_point)D2_FIX4(arc_centre.x),
203                                         (d2_point) D2_FIX4(arc_centre.y),
204                                         (d2_width) D2_FIX4(radius),
205                                         (d2_width) D2_FIX4(0),
206                                         (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees
207                                         (d2_s32)  D2_FIX16(0),
208                                         (d2_s32)  D2_FIX16(0),// 0 degrees
209                                         (d2_s32) D2_FIX16(-1),
210                                         flags);
211                 LV_ASSERT(D2_OK == result);
212             }
213 
214             arc_centre.x = coordinates.x2 - radius;
215             arc_centre.y = coordinates.y2 - radius;
216 
217             arc_area.x1 = coordinates.x2 - radius;
218             arc_area.y1 = coordinates.y2 - radius;
219             arc_area.x2 = coordinates.x2;
220             arc_area.y2 = coordinates.y2;
221 
222             if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
223                 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
224                             (d2_border)clip_arc.y2);
225 
226                 result = d2_renderwedge(u->d2_handle,
227                                         (d2_point)D2_FIX4(arc_centre.x),
228                                         (d2_point) D2_FIX4(arc_centre.y),
229                                         (d2_width) D2_FIX4(radius),
230                                         (d2_width) D2_FIX4(0),
231                                         (d2_s32) D2_FIX16(0),// 0 degrees
232                                         (d2_s32)  D2_FIX16(1),
233                                         (d2_s32)  D2_FIX16(1),// 90 degrees
234                                         (d2_s32) D2_FIX16(0),
235                                         flags);
236                 LV_ASSERT(D2_OK == result);
237             }
238 
239             arc_centre.x = coordinates.x1 + radius;
240             arc_centre.y = coordinates.y2 - radius;
241 
242             arc_area.x1 = coordinates.x1;
243             arc_area.y1 = coordinates.y2 - radius;
244             arc_area.x2 = coordinates.x1 + radius;
245             arc_area.y2 = coordinates.y2;
246 
247             if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
248                 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
249                             (d2_border)clip_arc.y2);
250 
251                 result = d2_renderwedge(u->d2_handle,
252                                         (d2_point)D2_FIX4(arc_centre.x),
253                                         (d2_point) D2_FIX4(arc_centre.y),
254                                         (d2_width) D2_FIX4(radius),
255                                         (d2_width) D2_FIX4(0),
256                                         (d2_s32) D2_FIX16((int16_t) -1), //90 degrees
257                                         (d2_s32)  D2_FIX16(0),
258                                         (d2_s32)  D2_FIX16(0), //180 degrees
259                                         (d2_s32) D2_FIX16(1),
260                                         flags);
261                 LV_ASSERT(D2_OK == result);
262             }
263 
264             /* reset the clip rectangle */
265             d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2,
266                         (d2_border)draw_area.y2);
267 
268             result = d2_renderbox(u->d2_handle,
269                                   (d2_width)D2_FIX4(coordinates.x1 + radius),
270                                   (d2_width)D2_FIX4(coordinates.y1),
271                                   (d2_width)D2_FIX4(lv_area_get_width(&coordinates) - (2 * radius)),
272                                   (d2_width)D2_FIX4(lv_area_get_height(&coordinates)));
273             LV_ASSERT(D2_OK == result);
274 
275             result = d2_renderbox(u->d2_handle,
276                                   (d2_width)D2_FIX4(coordinates.x1),
277                                   (d2_width)D2_FIX4(coordinates.y1 + radius),
278                                   (d2_width)D2_FIX4(radius),
279                                   (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius)));
280             LV_ASSERT(D2_OK == result);
281 
282             result = d2_renderbox(u->d2_handle,
283                                   (d2_width)D2_FIX4(coordinates.x2 - radius),
284                                   (d2_width)D2_FIX4(coordinates.y1 + radius),
285                                   (d2_width)D2_FIX4(radius),
286                                   (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius)));
287             LV_ASSERT(D2_OK == result);
288         }
289     }
290 
291     //
292     // Execute render operations
293     //
294 #if D2_RENDER_EACH_OPERATION
295     d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0);
296     d2_flushframe(u->d2_handle);
297 #endif
298 
299     if(LV_GRAD_DIR_NONE != dsc->grad.dir) {
300         d2_setalphamode(u->d2_handle, current_alpha_mode);
301         d2_setfillmode(u->d2_handle, d2_fm_color); //default
302     }
303 
304 #if LV_USE_OS
305     status = lv_mutex_unlock(u->pd2Mutex);
306     LV_ASSERT(LV_RESULT_OK == status);
307 #endif
308 }
309 
310 #endif /*LV_USE_DRAW_DAVE2D*/
311