1 /**
2  * @file lv_obj_draw.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_obj_draw.h"
10 #include "lv_obj.h"
11 #include "lv_disp.h"
12 #include "lv_indev.h"
13 
14 /*********************
15  *      DEFINES
16  *********************/
17 #define MY_CLASS &lv_obj_class
18 
19 /**********************
20  *      TYPEDEFS
21  **********************/
22 
23 /**********************
24  *  STATIC PROTOTYPES
25  **********************/
26 
27 /**********************
28  *  STATIC VARIABLES
29  **********************/
30 
31 /**********************
32  *      MACROS
33  **********************/
34 
35 /**********************
36  *   GLOBAL FUNCTIONS
37  **********************/
38 
lv_obj_init_draw_rect_dsc(lv_obj_t * obj,uint32_t part,lv_draw_rect_dsc_t * draw_dsc)39 void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc)
40 {
41     lv_opa_t opa = LV_OPA_COVER;
42     if(part != LV_PART_MAIN) {
43         opa = lv_obj_get_style_opa(obj, part);
44         if(opa <= LV_OPA_MIN) {
45             draw_dsc->bg_opa = LV_OPA_TRANSP;
46             draw_dsc->bg_img_opa = LV_OPA_TRANSP;
47             draw_dsc->border_opa = LV_OPA_TRANSP;
48             draw_dsc->outline_opa = LV_OPA_TRANSP;
49             draw_dsc->shadow_opa = LV_OPA_TRANSP;
50             return;
51         }
52     }
53 
54 #if LV_DRAW_COMPLEX
55     if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
56 
57     draw_dsc->radius = lv_obj_get_style_radius(obj, part);
58 
59     if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
60         draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
61         if(draw_dsc->bg_opa > LV_OPA_MIN) {
62             draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
63             const lv_grad_dsc_t * grad = lv_obj_get_style_bg_grad(obj, part);
64             if(grad && grad->dir != LV_GRAD_DIR_NONE) {
65                 lv_memcpy(&draw_dsc->bg_grad, grad, sizeof(*grad));
66             }
67             else {
68                 draw_dsc->bg_grad.dir = lv_obj_get_style_bg_grad_dir(obj, part);
69                 if(draw_dsc->bg_grad.dir != LV_GRAD_DIR_NONE) {
70                     draw_dsc->bg_grad.stops[0].color = lv_obj_get_style_bg_color_filtered(obj, part);
71                     draw_dsc->bg_grad.stops[1].color = lv_obj_get_style_bg_grad_color_filtered(obj, part);
72                     draw_dsc->bg_grad.stops[0].frac = lv_obj_get_style_bg_main_stop(obj, part);
73                     draw_dsc->bg_grad.stops[1].frac = lv_obj_get_style_bg_grad_stop(obj, part);
74                 }
75                 draw_dsc->bg_grad.dither = lv_obj_get_style_bg_dither_mode(obj, part);
76             }
77         }
78     }
79 
80     draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
81     if(draw_dsc->border_width) {
82         if(draw_dsc->border_opa != LV_OPA_TRANSP) {
83             draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
84             if(draw_dsc->border_opa > LV_OPA_MIN) {
85                 draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
86                 draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
87             }
88         }
89     }
90 
91     draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
92     if(draw_dsc->outline_width) {
93         if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
94             draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
95             if(draw_dsc->outline_opa > LV_OPA_MIN) {
96                 draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
97                 draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
98             }
99         }
100     }
101 
102     if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
103         draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
104         if(draw_dsc->bg_img_src) {
105             draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
106             if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
107                 if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
108                     draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
109                     draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
110                 }
111                 else {
112                     draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
113                     draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
114                     draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
115                 }
116             }
117         }
118     }
119 
120     if(draw_dsc->shadow_opa) {
121         draw_dsc->shadow_width = lv_obj_get_style_shadow_width(obj, part);
122         if(draw_dsc->shadow_width) {
123             if(draw_dsc->shadow_opa > LV_OPA_MIN) {
124                 draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part);
125                 if(draw_dsc->shadow_opa > LV_OPA_MIN) {
126                     draw_dsc->shadow_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
127                     draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
128                     draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part);
129                     draw_dsc->shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part);
130                 }
131             }
132         }
133     }
134 
135 #else /*LV_DRAW_COMPLEX*/
136     if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
137         draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
138         if(draw_dsc->bg_opa > LV_OPA_MIN) {
139             draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
140         }
141     }
142 
143     draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
144     if(draw_dsc->border_width) {
145         if(draw_dsc->border_opa != LV_OPA_TRANSP) {
146             draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
147             if(draw_dsc->border_opa > LV_OPA_MIN) {
148                 draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
149                 draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
150             }
151         }
152     }
153 
154     draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
155     if(draw_dsc->outline_width) {
156         if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
157             draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
158             if(draw_dsc->outline_opa > LV_OPA_MIN) {
159                 draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
160                 draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
161             }
162         }
163     }
164 
165     if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
166         draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
167         if(draw_dsc->bg_img_src) {
168             draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
169             if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
170                 if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
171                     draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
172                     draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
173                 }
174                 else {
175                     draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
176                     draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
177                     draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
178                 }
179             }
180         }
181     }
182 #endif
183 
184     if(part != LV_PART_MAIN) {
185         if(opa < LV_OPA_MAX) {
186             draw_dsc->bg_opa = (opa * draw_dsc->shadow_opa) >> 8;
187             draw_dsc->bg_img_opa = (opa * draw_dsc->shadow_opa) >> 8;
188             draw_dsc->border_opa = (opa * draw_dsc->shadow_opa) >> 8;
189             draw_dsc->outline_opa = (opa * draw_dsc->shadow_opa) >> 8;
190             draw_dsc->shadow_opa = (opa * draw_dsc->shadow_opa) >> 8;
191         }
192     }
193 }
194 
lv_obj_init_draw_label_dsc(lv_obj_t * obj,uint32_t part,lv_draw_label_dsc_t * draw_dsc)195 void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc)
196 {
197     draw_dsc->opa = lv_obj_get_style_text_opa(obj, part);
198     if(draw_dsc->opa <= LV_OPA_MIN) return;
199 
200     if(part != LV_PART_MAIN) {
201         lv_opa_t opa = lv_obj_get_style_opa(obj, part);
202         if(opa <= LV_OPA_MIN) {
203             draw_dsc->opa = LV_OPA_TRANSP;
204             return;
205         }
206         if(opa < LV_OPA_MAX) {
207             draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
208         }
209     }
210 
211     draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part);
212     draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part);
213     draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part);
214     draw_dsc->decor = lv_obj_get_style_text_decor(obj, part);
215 #if LV_DRAW_COMPLEX
216     if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
217 #endif
218 
219     draw_dsc->font = lv_obj_get_style_text_font(obj, part);
220 
221 #if LV_USE_BIDI
222     draw_dsc->bidi_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
223 #endif
224 
225     draw_dsc->align = lv_obj_get_style_text_align(obj, part);
226 }
227 
lv_obj_init_draw_img_dsc(lv_obj_t * obj,uint32_t part,lv_draw_img_dsc_t * draw_dsc)228 void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc)
229 {
230     draw_dsc->opa = lv_obj_get_style_img_opa(obj, part);
231     if(draw_dsc->opa <= LV_OPA_MIN) return;
232 
233     if(part != LV_PART_MAIN) {
234         lv_opa_t opa = lv_obj_get_style_opa(obj, part);
235         if(opa <= LV_OPA_MIN) {
236             draw_dsc->opa = LV_OPA_TRANSP;
237             return;
238         }
239         if(opa < LV_OPA_MAX) {
240             draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
241         }
242     }
243 
244     draw_dsc->angle = 0;
245     draw_dsc->zoom = LV_IMG_ZOOM_NONE;
246     draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2;
247     draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2;
248 
249     draw_dsc->recolor_opa = lv_obj_get_style_img_recolor_opa(obj, part);
250     if(draw_dsc->recolor_opa > 0) {
251         draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part);
252     }
253 #if LV_DRAW_COMPLEX
254     if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
255 #endif
256 }
257 
lv_obj_init_draw_line_dsc(lv_obj_t * obj,uint32_t part,lv_draw_line_dsc_t * draw_dsc)258 void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc)
259 {
260     draw_dsc->opa = lv_obj_get_style_line_opa(obj, part);
261     if(draw_dsc->opa <= LV_OPA_MIN)  return;
262 
263     if(part != LV_PART_MAIN) {
264         lv_opa_t opa = lv_obj_get_style_opa(obj, part);
265         if(opa <= LV_OPA_MIN) {
266             draw_dsc->opa = LV_OPA_TRANSP;
267             return;
268         }
269         if(opa < LV_OPA_MAX) {
270             draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
271         }
272     }
273 
274     draw_dsc->width = lv_obj_get_style_line_width(obj, part);
275     if(draw_dsc->width == 0) return;
276 
277     draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part);
278 
279     draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part);
280     if(draw_dsc->dash_width) {
281         draw_dsc->dash_gap = lv_obj_get_style_line_dash_gap(obj, part);
282     }
283 
284     draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part);
285     draw_dsc->round_end = draw_dsc->round_start;
286 
287 #if LV_DRAW_COMPLEX
288     if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
289 #endif
290 }
291 
lv_obj_init_draw_arc_dsc(lv_obj_t * obj,uint32_t part,lv_draw_arc_dsc_t * draw_dsc)292 void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc)
293 {
294     draw_dsc->width = lv_obj_get_style_arc_width(obj, part);
295     if(draw_dsc->width == 0) return;
296 
297     draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part);
298     if(draw_dsc->opa <= LV_OPA_MIN)  return;
299 
300     if(part != LV_PART_MAIN) {
301         lv_opa_t opa = lv_obj_get_style_opa(obj, part);
302         if(opa <= LV_OPA_MIN) {
303             draw_dsc->opa = LV_OPA_TRANSP;
304             return;
305         }
306         if(opa < LV_OPA_MAX) {
307             draw_dsc->opa = (opa * draw_dsc->opa) >> 8;
308         }
309     }
310 
311     draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part);
312     draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part);
313 
314     draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
315 
316 #if LV_DRAW_COMPLEX
317     if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
318 #endif
319 }
320 
lv_obj_calculate_ext_draw_size(lv_obj_t * obj,uint32_t part)321 lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part)
322 {
323     lv_coord_t s = 0;
324 
325     lv_coord_t sh_width = lv_obj_get_style_shadow_width(obj, part);
326     if(sh_width) {
327         lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part);
328         if(sh_opa > LV_OPA_MIN) {
329             sh_width = sh_width / 2 + 1;    /*The blur adds only half width*/
330             sh_width += lv_obj_get_style_shadow_spread(obj, part);
331             lv_coord_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
332             lv_coord_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
333             sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y));
334             s = LV_MAX(s, sh_width);
335         }
336     }
337 
338     lv_coord_t outline_width = lv_obj_get_style_outline_width(obj, part);
339     if(outline_width) {
340         lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part);
341         if(outline_opa > LV_OPA_MIN) {
342             lv_coord_t outline_pad = lv_obj_get_style_outline_pad(obj, part);
343             s = LV_MAX(s, outline_pad + outline_width);
344         }
345     }
346 
347     lv_coord_t w = lv_obj_get_style_transform_width(obj, part);
348     lv_coord_t h = lv_obj_get_style_transform_height(obj, part);
349     lv_coord_t wh = LV_MAX(w, h);
350     if(wh > 0) s += wh;
351 
352     return s;
353 }
354 
lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc,lv_draw_ctx_t * draw_ctx)355 void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx)
356 {
357     lv_memset_00(dsc, sizeof(lv_obj_draw_part_dsc_t));
358     dsc->draw_ctx = draw_ctx;
359 }
360 
lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc,const lv_obj_class_t * class_p,uint32_t type)361 bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type)
362 {
363     if(dsc->class_p == class_p && dsc->type == type) return true;
364     else return false;
365 }
366 
lv_obj_refresh_ext_draw_size(lv_obj_t * obj)367 void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
368 {
369     LV_ASSERT_OBJ(obj, MY_CLASS);
370 
371     lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj);
372     lv_coord_t s_new = 0;
373     lv_event_send(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new);
374 
375     if(s_new != s_old) lv_obj_invalidate(obj);
376 
377     /*Store the result if the special attrs already allocated*/
378     if(obj->spec_attr) {
379         obj->spec_attr->ext_draw_size = s_new;
380     }
381     /*Allocate spec. attrs. only if the result is not zero.
382      *Zero is the default value if the spec. attr. are not defined.*/
383     else if(s_new != 0) {
384         lv_obj_allocate_spec_attr(obj);
385         obj->spec_attr->ext_draw_size = s_new;
386     }
387 
388     if(s_new != s_old) lv_obj_invalidate(obj);
389 }
390 
_lv_obj_get_ext_draw_size(const lv_obj_t * obj)391 lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj)
392 {
393     if(obj->spec_attr) return obj->spec_attr->ext_draw_size;
394     else return 0;
395 }
396 
_lv_obj_get_layer_type(const lv_obj_t * obj)397 lv_layer_type_t _lv_obj_get_layer_type(const lv_obj_t * obj)
398 {
399 
400     if(obj->spec_attr) return obj->spec_attr->layer_type;
401     else return LV_LAYER_TYPE_NONE;
402 }
403 
404 /**********************
405  *   STATIC FUNCTIONS
406  **********************/
407