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