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