1 #include "lv_draw_dave2d.h"
2 #if LV_USE_DRAW_DAVE2D
3
4 #include "../../../misc/lv_area_private.h"
5
6 static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area,
7 const lv_area_t * inner_area,
8 int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa);
9
10 static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area,
11 const lv_area_t * inner_area,
12 lv_color_t color, lv_opa_t opa);
13
lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit,const lv_draw_border_dsc_t * dsc,const lv_area_t * coords)14 void lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
15 const lv_area_t * coords)
16 {
17 if(dsc->opa <= LV_OPA_MIN) return;
18 if(dsc->width == 0) return;
19 if(dsc->side == LV_BORDER_SIDE_NONE) return;
20
21 int32_t coords_w = lv_area_get_width(coords);
22 int32_t coords_h = lv_area_get_height(coords);
23 int32_t rout = dsc->radius;
24 int32_t short_side = LV_MIN(coords_w, coords_h);
25 if(rout > short_side >> 1) rout = short_side >> 1;
26
27 /*Get the inner area*/
28 lv_area_t area_inner;
29 lv_area_copy(&area_inner, coords);
30 area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width + rout));
31 area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width + rout));
32 area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width + rout));
33 area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width + rout));
34
35 int32_t rin = rout - dsc->width;
36 if(rin < 0) rin = 0;
37
38 if(rout == 0 && rin == 0) {
39 dave2d_draw_border_simple(draw_unit, coords, &area_inner, dsc->color, dsc->opa);
40 }
41 else {
42 dave2d_draw_border_complex(draw_unit, coords, &area_inner, rout, rin, dsc->color, dsc->opa);
43 }
44
45 }
46
dave2d_draw_border_simple(lv_draw_dave2d_unit_t * u,const lv_area_t * outer_area,const lv_area_t * inner_area,lv_color_t color,lv_opa_t opa)47 static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * u, const lv_area_t * outer_area,
48 const lv_area_t * inner_area,
49 lv_color_t color, lv_opa_t opa)
50
51 {
52
53 lv_area_t clip_area;
54 lv_area_t local_outer_area;
55 lv_area_t local_inner_area;
56 int32_t x;
57 int32_t y;
58 bool is_common;
59
60 is_common = lv_area_intersect(&clip_area, outer_area, u->base_unit.clip_area);
61 if(!is_common) return;
62
63 #if LV_USE_OS
64 lv_result_t status;
65 status = lv_mutex_lock(u->pd2Mutex);
66 LV_ASSERT(LV_RESULT_OK == status);
67 #endif
68
69 local_outer_area = *outer_area;
70 local_inner_area = *inner_area;
71
72 x = 0 - u->base_unit.target_layer->buf_area.x1;
73 y = 0 - u->base_unit.target_layer->buf_area.y1;
74
75 lv_area_move(&clip_area, x, y);
76 lv_area_move(&local_outer_area, x, y);
77 lv_area_move(&local_inner_area, x, y);
78
79 #if D2_RENDER_EACH_OPERATION
80 d2_selectrenderbuffer(u->d2_handle, u->renderbuffer);
81 #endif
82 //
83 // Generate render operations
84 //
85
86 d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer);
87
88 d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color));
89 d2_setalpha(u->d2_handle, opa);
90 d2_cliprect(u->d2_handle, (d2_border)clip_area.x1, (d2_border)clip_area.y1, (d2_border)clip_area.x2,
91 (d2_border)clip_area.y2);
92
93 lv_area_t a;
94
95 bool top_side = local_outer_area.y1 <= local_inner_area.y1;
96 bool bottom_side = local_outer_area.y2 >= local_inner_area.y2;
97 bool left_side = local_outer_area.x1 <= local_inner_area.x1;
98 bool right_side = local_outer_area.x2 >= local_inner_area.x2;
99
100 /*Top*/
101 a.x1 = local_outer_area.x1;
102 a.x2 = local_outer_area.x2;
103 a.y1 = local_outer_area.y1;
104 a.y2 = local_inner_area.y1 - 1;
105 if(top_side) {
106 d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1),
107 (d2_point)D2_FIX4(a.y1),
108 (d2_point)D2_FIX4(lv_area_get_width(&a)),
109 (d2_point)D2_FIX4(lv_area_get_height(&a)));
110 }
111
112 /*Bottom*/
113 a.y1 = local_inner_area.y2 + 1;
114 a.y2 = local_outer_area.y2;
115 if(bottom_side) {
116 d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1),
117 (d2_point)D2_FIX4(a.y1),
118 (d2_point)D2_FIX4(lv_area_get_width(&a)),
119 (d2_point)D2_FIX4(lv_area_get_height(&a)));
120 }
121
122 /*Left*/
123 a.x1 = local_outer_area.x1;
124 a.x2 = local_inner_area.x1 - 1;
125 a.y1 = (top_side) ? local_inner_area.y1 : local_outer_area.y1;
126 a.y2 = (bottom_side) ? local_inner_area.y2 : local_outer_area.y2;
127 if(left_side) {
128 d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1),
129 (d2_point)D2_FIX4(a.y1),
130 (d2_point)D2_FIX4(lv_area_get_width(&a)),
131 (d2_point)D2_FIX4(lv_area_get_height(&a)));
132 }
133
134 /*Right*/
135 a.x1 = local_inner_area.x2 + 1;
136 a.x2 = local_outer_area.x2;
137 if(right_side) {
138 d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1),
139 (d2_point)D2_FIX4(a.y1),
140 (d2_point)D2_FIX4(lv_area_get_width(&a)),
141 (d2_point)D2_FIX4(lv_area_get_height(&a)));
142 }
143
144 //
145 // Execute render operations
146 //
147 #if D2_RENDER_EACH_OPERATION
148 d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0);
149 d2_flushframe(u->d2_handle);
150 #endif
151
152 #if LV_USE_OS
153 status = lv_mutex_unlock(u->pd2Mutex);
154 LV_ASSERT(LV_RESULT_OK == status);
155 #endif
156 }
157
dave2d_draw_border_complex(lv_draw_dave2d_unit_t * u,const lv_area_t * orig_outer_area,const lv_area_t * orig_inner_area,int32_t rout,int32_t rin,lv_color_t color,lv_opa_t opa)158 static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * u, const lv_area_t * orig_outer_area,
159 const lv_area_t * orig_inner_area,
160 int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa)
161 {
162 /*Get clipped draw area which is the real draw area.
163 *It is always the same or inside `coords`*/
164 lv_area_t draw_area;
165 lv_area_t outer_area;
166 lv_area_t inner_area;
167 int32_t x;
168 int32_t y;
169 d2_s32 result;
170 d2_u32 flags = 0;
171
172 outer_area = *orig_outer_area;
173 inner_area = *orig_inner_area;
174
175 if(!lv_area_intersect(&draw_area, &outer_area, u->base_unit.clip_area)) return;
176
177 #if LV_USE_OS
178 lv_result_t status;
179 status = lv_mutex_lock(u->pd2Mutex);
180 LV_ASSERT(LV_RESULT_OK == status);
181 #endif
182
183 x = 0 - u->base_unit.target_layer->buf_area.x1;
184 y = 0 - u->base_unit.target_layer->buf_area.y1;
185
186 lv_area_move(&draw_area, x, y);
187 lv_area_move(&outer_area, x, y);
188 lv_area_move(&inner_area, x, y);
189
190 #if D2_RENDER_EACH_OPERATION
191 d2_selectrenderbuffer(u->d2_handle, u->renderbuffer);
192 #endif
193 //
194 // Generate render operations
195 //
196
197 d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer);
198
199 d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color));
200 d2_setalpha(u->d2_handle, opa);
201 d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2,
202 (d2_border)draw_area.y2);
203
204 lv_area_t blend_area;
205 /*Calculate the x and y coordinates where the straight parts area are */
206 lv_area_t core_area;
207 core_area.x1 = LV_MAX(outer_area.x1 + rout, inner_area.x1);
208 core_area.x2 = LV_MIN(outer_area.x2 - rout, inner_area.x2);
209 core_area.y1 = LV_MAX(outer_area.y1 + rout, inner_area.y1);
210 core_area.y2 = LV_MIN(outer_area.y2 - rout, inner_area.y2);
211
212 bool top_side = outer_area.y1 <= inner_area.y1;
213 bool bottom_side = outer_area.y2 >= inner_area.y2;
214
215 /*No masks*/
216 bool left_side = outer_area.x1 <= inner_area.x1;
217 bool right_side = outer_area.x2 >= inner_area.x2;
218
219 /*Draw the straight lines first */
220 if(top_side) {
221 blend_area.x1 = core_area.x1;
222 blend_area.x2 = core_area.x2;
223 blend_area.y1 = outer_area.y1;
224 blend_area.y2 = inner_area.y1 - 1;
225 d2_renderbox(u->d2_handle,
226 (d2_point)D2_FIX4(blend_area.x1),
227 (d2_point)D2_FIX4(blend_area.y1),
228 (d2_point)D2_FIX4(lv_area_get_width(&blend_area)),
229 (d2_point)D2_FIX4(lv_area_get_height(&blend_area)));
230 }
231
232 if(bottom_side) {
233 blend_area.x1 = core_area.x1;
234 blend_area.x2 = core_area.x2;
235 blend_area.y1 = inner_area.y2 + 1;
236 blend_area.y2 = outer_area.y2;
237 d2_renderbox(u->d2_handle,
238 (d2_point)D2_FIX4(blend_area.x1),
239 (d2_point)D2_FIX4(blend_area.y1),
240 (d2_point)D2_FIX4(lv_area_get_width(&blend_area)),
241 (d2_point)D2_FIX4(lv_area_get_height(&blend_area)));
242 }
243
244 if(left_side) {
245 blend_area.x1 = outer_area.x1;
246 blend_area.x2 = inner_area.x1 - 1;
247 blend_area.y1 = core_area.y1;
248 blend_area.y2 = core_area.y2;
249 d2_renderbox(u->d2_handle,
250 (d2_point)D2_FIX4(blend_area.x1),
251 (d2_point)D2_FIX4(blend_area.y1),
252 (d2_point)D2_FIX4(lv_area_get_width(&blend_area)),
253 (d2_point)D2_FIX4(lv_area_get_height(&blend_area)));
254 }
255
256 if(right_side) {
257 blend_area.x1 = inner_area.x2 + 1;
258 blend_area.x2 = outer_area.x2;
259 blend_area.y1 = core_area.y1;
260 blend_area.y2 = core_area.y2;
261 d2_renderbox(u->d2_handle,
262 (d2_point)D2_FIX4(blend_area.x1),
263 (d2_point)D2_FIX4(blend_area.y1),
264 (d2_point)D2_FIX4(lv_area_get_width(&blend_area)),
265 (d2_point)D2_FIX4(lv_area_get_height(&blend_area)));
266 }
267
268 /*Draw the corners*/
269 int32_t blend_w;
270 /*Left corners*/
271 blend_area.x1 = draw_area.x1;
272 blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1);
273
274 blend_w = lv_area_get_width(&blend_area);
275
276 if(blend_w > 0) {
277 d2_s32 aa;
278 aa = d2_getantialiasing(u->d2_handle);
279 d2_setantialiasing(u->d2_handle, 0); //Don't blend with the background according to coverage value
280
281 if(left_side || top_side) {
282 lv_area_t arc_area;
283 lv_area_t clip_arc;
284
285 arc_area.x1 = core_area.x1 - rout;
286 arc_area.y1 = core_area.y1 - rout;
287 arc_area.x2 = core_area.x1;
288 arc_area.y2 = core_area.y1;
289
290 if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
291 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
292 (d2_border)clip_arc.y2);
293 result = d2_renderwedge(u->d2_handle,
294 (d2_point)D2_FIX4(core_area.x1),
295 (d2_point) D2_FIX4(core_area.y1),
296 (d2_width) D2_FIX4(rout),
297 (d2_width) D2_FIX4((rout - rin)),
298 (d2_s32) D2_FIX16(0), // 180 Degrees
299 (d2_s32) D2_FIX16((int16_t) -1),
300 (d2_s32) D2_FIX16((int16_t) -1),//( 270 Degrees
301 (d2_s32) D2_FIX16(0),
302 flags);
303 LV_ASSERT(D2_OK == result);
304 }
305
306 }
307
308 if(left_side || bottom_side) {
309 lv_area_t arc_area;
310 lv_area_t clip_arc;
311
312 arc_area.x1 = core_area.x1 - rout;
313 arc_area.y1 = core_area.y2;
314 arc_area.x2 = core_area.x1;
315 arc_area.y2 = core_area.y2 + rout;
316
317 if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
318
319 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
320 (d2_border)clip_arc.y2);
321 result = d2_renderwedge(u->d2_handle,
322 (d2_point)D2_FIX4(core_area.x1),
323 (d2_point) D2_FIX4(core_area.y2),
324 (d2_width) D2_FIX4(rout),
325 (d2_width) D2_FIX4((rout - rin)),
326 (d2_s32) D2_FIX16((int16_t) -1), //90 degrees
327 (d2_s32) D2_FIX16(0),
328 (d2_s32) D2_FIX16(0), //180 degrees
329 (d2_s32) D2_FIX16(1),
330 flags);
331 LV_ASSERT(D2_OK == result);
332 }
333 }
334
335 /*Right corners*/
336 blend_area.x1 = LV_MAX(draw_area.x1, blend_area.x2 + 1); /*To not overlap with the left side*/
337 blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1);
338
339 blend_area.x2 = draw_area.x2;
340 blend_w = lv_area_get_width(&blend_area);
341
342 if(blend_w > 0) {
343 if(right_side || top_side) {
344
345 lv_area_t arc_area;
346 lv_area_t clip_arc;
347
348 arc_area.x1 = core_area.x2;
349 arc_area.y1 = core_area.y1 - rout;
350 arc_area.x2 = core_area.x2 + rout;
351 arc_area.y2 = core_area.y1;
352
353 if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
354
355 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
356 (d2_border)clip_arc.y2);
357 result = d2_renderwedge(u->d2_handle,
358 (d2_point)D2_FIX4(core_area.x2),
359 (d2_point) D2_FIX4(core_area.y1),
360 (d2_width) D2_FIX4(rout),
361 (d2_width) D2_FIX4((rout - rin)),
362 (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees
363 (d2_s32) D2_FIX16(0),
364 (d2_s32) D2_FIX16(0),// 0 degrees
365 (d2_s32) D2_FIX16(-1),
366 flags);
367 LV_ASSERT(D2_OK == result);
368 }
369
370 }
371
372 if(right_side || bottom_side) {
373 lv_area_t arc_area;
374 lv_area_t clip_arc;
375
376 arc_area.x1 = core_area.x2;
377 arc_area.y1 = core_area.y2;
378 arc_area.x2 = core_area.x2 + rout;
379 arc_area.y2 = core_area.y2 + rout;
380
381 if(lv_area_intersect(&clip_arc, &arc_area, &draw_area)) {
382
383 d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2,
384 (d2_border)clip_arc.y2);
385 result = d2_renderwedge(u->d2_handle,
386 (d2_point)D2_FIX4(core_area.x2),
387 (d2_point) D2_FIX4(core_area.y2),
388 (d2_width) D2_FIX4(rout),
389 (d2_width) D2_FIX4((rout - rin)),
390 (d2_s32) D2_FIX16(0),// 0 degrees
391 (d2_s32) D2_FIX16(1),
392 (d2_s32) D2_FIX16(1),// 90 degrees
393 (d2_s32) D2_FIX16(0),
394 flags);
395 LV_ASSERT(D2_OK == result);
396 }
397 }
398 }
399 d2_setantialiasing(u->d2_handle, aa); //restore original setting
400 }
401
402 //
403 // Execute render operations
404 //
405 #if D2_RENDER_EACH_OPERATION
406 d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0);
407 d2_flushframe(u->d2_handle);
408 #endif
409
410 #if LV_USE_OS
411 status = lv_mutex_unlock(u->pd2Mutex);
412 LV_ASSERT(LV_RESULT_OK == status);
413 #endif
414
415 }
416
417 #endif /*LV_USE_DRAW_DAVE2D*/
418