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