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