1 /**
2 * @file lv_img.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_img.h"
10 #if LV_USE_IMG != 0
11
12 #include "../misc/lv_assert.h"
13 #include "../draw/lv_img_decoder.h"
14 #include "../misc/lv_fs.h"
15 #include "../misc/lv_txt.h"
16 #include "../misc/lv_math.h"
17 #include "../misc/lv_log.h"
18
19 /*********************
20 * DEFINES
21 *********************/
22 #define MY_CLASS &lv_img_class
23
24 /**********************
25 * TYPEDEFS
26 **********************/
27
28 /**********************
29 * STATIC PROTOTYPES
30 **********************/
31 static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
32 static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
33 static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e);
34 static void draw_img(lv_event_t * e);
35
36 /**********************
37 * STATIC VARIABLES
38 **********************/
39 const lv_obj_class_t lv_img_class = {
40 .constructor_cb = lv_img_constructor,
41 .destructor_cb = lv_img_destructor,
42 .event_cb = lv_img_event,
43 .width_def = LV_SIZE_CONTENT,
44 .height_def = LV_SIZE_CONTENT,
45 .instance_size = sizeof(lv_img_t),
46 .base_class = &lv_obj_class
47 };
48
49 /**********************
50 * MACROS
51 **********************/
52
53 /**********************
54 * GLOBAL FUNCTIONS
55 **********************/
56
lv_img_create(lv_obj_t * parent)57 lv_obj_t * lv_img_create(lv_obj_t * parent)
58 {
59 LV_LOG_INFO("begin");
60 lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
61 lv_obj_class_init_obj(obj);
62 return obj;
63 }
64
65 /*=====================
66 * Setter functions
67 *====================*/
68
lv_img_set_src(lv_obj_t * obj,const void * src)69 void lv_img_set_src(lv_obj_t * obj, const void * src)
70 {
71 LV_ASSERT_OBJ(obj, MY_CLASS);
72
73 lv_obj_invalidate(obj);
74
75 lv_img_src_t src_type = lv_img_src_get_type(src);
76 lv_img_t * img = (lv_img_t *)obj;
77
78 #if LV_USE_LOG && LV_LOG_LEVEL >= LV_LOG_LEVEL_INFO
79 switch(src_type) {
80 case LV_IMG_SRC_FILE:
81 LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_FILE` type found");
82 break;
83 case LV_IMG_SRC_VARIABLE:
84 LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_VARIABLE` type found");
85 break;
86 case LV_IMG_SRC_SYMBOL:
87 LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_SYMBOL` type found");
88 break;
89 default:
90 LV_LOG_WARN("lv_img_set_src: unknown type");
91 }
92 #endif
93
94 /*If the new source type is unknown free the memories of the old source*/
95 if(src_type == LV_IMG_SRC_UNKNOWN) {
96 LV_LOG_WARN("lv_img_set_src: unknown image type");
97 if(img->src_type == LV_IMG_SRC_SYMBOL || img->src_type == LV_IMG_SRC_FILE) {
98 lv_mem_free((void *)img->src);
99 }
100 img->src = NULL;
101 img->src_type = LV_IMG_SRC_UNKNOWN;
102 return;
103 }
104
105 lv_img_header_t header;
106 lv_img_decoder_get_info(src, &header);
107
108 /*Save the source*/
109 if(src_type == LV_IMG_SRC_VARIABLE) {
110 /*If memory was allocated because of the previous `src_type` then free it*/
111 if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) {
112 lv_mem_free((void *)img->src);
113 }
114 img->src = src;
115 }
116 else if(src_type == LV_IMG_SRC_FILE || src_type == LV_IMG_SRC_SYMBOL) {
117 /*If the new and the old src are the same then it was only a refresh.*/
118 if(img->src != src) {
119 const void * old_src = NULL;
120 /*If memory was allocated because of the previous `src_type` then save its pointer and free after allocation.
121 *It's important to allocate first to be sure the new data will be on a new address.
122 *Else `img_cache` wouldn't see the change in source.*/
123 if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) {
124 old_src = img->src;
125 }
126 char * new_str = lv_mem_alloc(strlen(src) + 1);
127 LV_ASSERT_MALLOC(new_str);
128 if(new_str == NULL) return;
129 strcpy(new_str, src);
130 img->src = new_str;
131
132 if(old_src) lv_mem_free((void *)old_src);
133 }
134 }
135
136 if(src_type == LV_IMG_SRC_SYMBOL) {
137 /*`lv_img_dsc_get_info` couldn't set the with and height of a font so set it here*/
138 const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
139 lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
140 lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);
141 lv_point_t size;
142 lv_txt_get_size(&size, src, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
143 header.w = size.x;
144 header.h = size.y;
145 }
146
147 img->src_type = src_type;
148 img->w = header.w;
149 img->h = header.h;
150 img->cf = header.cf;
151 img->pivot.x = header.w / 2;
152 img->pivot.y = header.h / 2;
153
154 lv_obj_refresh_self_size(obj);
155
156 /*Provide enough room for the rotated corners*/
157 if(img->angle || img->zoom != LV_IMG_ZOOM_NONE) lv_obj_refresh_ext_draw_size(obj);
158
159 lv_obj_invalidate(obj);
160 }
161
lv_img_set_offset_x(lv_obj_t * obj,lv_coord_t x)162 void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x)
163 {
164 LV_ASSERT_OBJ(obj, MY_CLASS);
165
166 lv_img_t * img = (lv_img_t *)obj;
167
168 x = x % img->w;
169
170 img->offset.x = x;
171 lv_obj_invalidate(obj);
172 }
173
lv_img_set_offset_y(lv_obj_t * obj,lv_coord_t y)174 void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y)
175 {
176 LV_ASSERT_OBJ(obj, MY_CLASS);
177
178 lv_img_t * img = (lv_img_t *)obj;
179
180 y = y % img->h;
181
182 img->offset.y = y;
183 lv_obj_invalidate(obj);
184 }
185
lv_img_set_angle(lv_obj_t * obj,int16_t angle)186 void lv_img_set_angle(lv_obj_t * obj, int16_t angle)
187 {
188 if(angle < 0 || angle >= 3600) angle = angle % 3600;
189
190 lv_img_t * img = (lv_img_t *)obj;
191 if(angle == img->angle) return;
192
193 lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
194 transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8;
195
196 lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
197
198 lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
199 lv_coord_t w = lv_obj_get_width(obj);
200 lv_coord_t h = lv_obj_get_height(obj);
201 lv_area_t a;
202 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle + img->angle, transf_zoom, &img->pivot);
203 a.x1 += obj->coords.x1;
204 a.y1 += obj->coords.y1;
205 a.x2 += obj->coords.x1;
206 a.y2 += obj->coords.y1;
207 lv_obj_invalidate_area(obj, &a);
208
209 img->angle = angle;
210 lv_obj_refresh_ext_draw_size(obj);
211
212 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle + img->angle, transf_zoom, &img->pivot);
213 a.x1 += obj->coords.x1;
214 a.y1 += obj->coords.y1;
215 a.x2 += obj->coords.x1;
216 a.y2 += obj->coords.y1;
217 lv_obj_invalidate_area(obj, &a);
218 }
219
lv_img_set_pivot(lv_obj_t * obj,lv_coord_t x,lv_coord_t y)220 void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
221 {
222 lv_img_t * img = (lv_img_t *)obj;
223 if(img->pivot.x == x && img->pivot.y == y) return;
224
225 lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
226 transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8;
227
228 lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
229 transf_angle += img->angle;
230
231 lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
232 lv_coord_t w = lv_obj_get_width(obj);
233 lv_coord_t h = lv_obj_get_height(obj);
234 lv_area_t a;
235 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot);
236 a.x1 += obj->coords.x1;
237 a.y1 += obj->coords.y1;
238 a.x2 += obj->coords.x1;
239 a.y2 += obj->coords.y1;
240 lv_obj_invalidate_area(obj, &a);
241
242 img->pivot.x = x;
243 img->pivot.y = y;
244 lv_obj_refresh_ext_draw_size(obj);
245
246 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot);
247 a.x1 += obj->coords.x1;
248 a.y1 += obj->coords.y1;
249 a.x2 += obj->coords.x1;
250 a.y2 += obj->coords.y1;
251 lv_obj_invalidate_area(obj, &a);
252 }
253
lv_img_set_zoom(lv_obj_t * obj,uint16_t zoom)254 void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom)
255 {
256 lv_img_t * img = (lv_img_t *)obj;
257 if(zoom == img->zoom) return;
258
259 if(zoom == 0) zoom = 1;
260
261 lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
262
263 lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
264 transf_angle += img->angle;
265
266 lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/
267 lv_coord_t w = lv_obj_get_width(obj);
268 lv_coord_t h = lv_obj_get_height(obj);
269 lv_area_t a;
270 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot);
271 a.x1 += obj->coords.x1 - 1;
272 a.y1 += obj->coords.y1 - 1;
273 a.x2 += obj->coords.x1 + 1;
274 a.y2 += obj->coords.y1 + 1;
275 lv_obj_invalidate_area(obj, &a);
276
277 img->zoom = zoom;
278 lv_obj_refresh_ext_draw_size(obj);
279
280 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, ((int32_t)transf_zoom * img->zoom) >> 8, &img->pivot);
281 a.x1 += obj->coords.x1 - 1;
282 a.y1 += obj->coords.y1 - 1;
283 a.x2 += obj->coords.x1 + 1;
284 a.y2 += obj->coords.y1 + 1;
285 lv_obj_invalidate_area(obj, &a);
286 }
287
lv_img_set_antialias(lv_obj_t * obj,bool antialias)288 void lv_img_set_antialias(lv_obj_t * obj, bool antialias)
289 {
290 lv_img_t * img = (lv_img_t *)obj;
291 if(antialias == img->antialias) return;
292
293 img->antialias = antialias;
294 lv_obj_invalidate(obj);
295 }
296
lv_img_set_size_mode(lv_obj_t * obj,lv_img_size_mode_t mode)297 void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode)
298 {
299 LV_ASSERT_OBJ(obj, MY_CLASS);
300 lv_img_t * img = (lv_img_t *)obj;
301 if(mode == img->obj_size_mode) return;
302
303 img->obj_size_mode = mode;
304 lv_obj_invalidate(obj);
305 }
306
307 /*=====================
308 * Getter functions
309 *====================*/
310
lv_img_get_src(lv_obj_t * obj)311 const void * lv_img_get_src(lv_obj_t * obj)
312 {
313 LV_ASSERT_OBJ(obj, MY_CLASS);
314
315 lv_img_t * img = (lv_img_t *)obj;
316
317 return img->src;
318 }
319
lv_img_get_offset_x(lv_obj_t * obj)320 lv_coord_t lv_img_get_offset_x(lv_obj_t * obj)
321 {
322 LV_ASSERT_OBJ(obj, MY_CLASS);
323
324 lv_img_t * img = (lv_img_t *)obj;
325
326 return img->offset.x;
327 }
328
lv_img_get_offset_y(lv_obj_t * obj)329 lv_coord_t lv_img_get_offset_y(lv_obj_t * obj)
330 {
331 LV_ASSERT_OBJ(obj, MY_CLASS);
332
333 lv_img_t * img = (lv_img_t *)obj;
334
335 return img->offset.y;
336 }
337
lv_img_get_angle(lv_obj_t * obj)338 uint16_t lv_img_get_angle(lv_obj_t * obj)
339 {
340 LV_ASSERT_OBJ(obj, MY_CLASS);
341
342 lv_img_t * img = (lv_img_t *)obj;
343
344 return img->angle;
345 }
346
lv_img_get_pivot(lv_obj_t * obj,lv_point_t * pivot)347 void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot)
348 {
349 LV_ASSERT_OBJ(obj, MY_CLASS);
350
351 lv_img_t * img = (lv_img_t *)obj;
352
353 *pivot = img->pivot;
354 }
355
lv_img_get_zoom(lv_obj_t * obj)356 uint16_t lv_img_get_zoom(lv_obj_t * obj)
357 {
358 LV_ASSERT_OBJ(obj, MY_CLASS);
359
360 lv_img_t * img = (lv_img_t *)obj;
361
362 return img->zoom;
363 }
364
lv_img_get_antialias(lv_obj_t * obj)365 bool lv_img_get_antialias(lv_obj_t * obj)
366 {
367 LV_ASSERT_OBJ(obj, MY_CLASS);
368
369 lv_img_t * img = (lv_img_t *)obj;
370
371 return img->antialias ? true : false;
372 }
373
lv_img_get_size_mode(lv_obj_t * obj)374 lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj)
375 {
376 LV_ASSERT_OBJ(obj, MY_CLASS);
377 lv_img_t * img = (lv_img_t *)obj;
378 return img->obj_size_mode;
379 }
380
381 /**********************
382 * STATIC FUNCTIONS
383 **********************/
384
lv_img_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)385 static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
386 {
387 LV_UNUSED(class_p);
388 LV_TRACE_OBJ_CREATE("begin");
389
390 lv_img_t * img = (lv_img_t *)obj;
391
392 img->src = NULL;
393 img->src_type = LV_IMG_SRC_UNKNOWN;
394 img->cf = LV_IMG_CF_UNKNOWN;
395 img->w = lv_obj_get_width(obj);
396 img->h = lv_obj_get_height(obj);
397 img->angle = 0;
398 img->zoom = LV_IMG_ZOOM_NONE;
399 img->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
400 img->offset.x = 0;
401 img->offset.y = 0;
402 img->pivot.x = 0;
403 img->pivot.y = 0;
404 img->obj_size_mode = LV_IMG_SIZE_MODE_VIRTUAL;
405
406 lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE);
407 lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST);
408
409 LV_TRACE_OBJ_CREATE("finished");
410 }
411
lv_img_destructor(const lv_obj_class_t * class_p,lv_obj_t * obj)412 static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
413 {
414 LV_UNUSED(class_p);
415 lv_img_t * img = (lv_img_t *)obj;
416 if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) {
417 lv_mem_free((void *)img->src);
418 img->src = NULL;
419 img->src_type = LV_IMG_SRC_UNKNOWN;
420 }
421 }
422
lv_img_get_transformed_size(lv_obj_t * obj)423 static lv_point_t lv_img_get_transformed_size(lv_obj_t * obj)
424 {
425 lv_img_t * img = (lv_img_t *)obj;
426
427 int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
428 zoom_final = (zoom_final * img->zoom) >> 8;
429 int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
430 angle_final += img->angle;
431
432 lv_area_t area_transform;
433 _lv_img_buf_get_transformed_area(&area_transform, img->w, img->h,
434 angle_final, zoom_final, &img->pivot);
435
436 return (lv_point_t) {
437 lv_area_get_width(&area_transform), lv_area_get_height(&area_transform)
438 };
439 }
440
lv_img_event(const lv_obj_class_t * class_p,lv_event_t * e)441 static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e)
442 {
443 LV_UNUSED(class_p);
444
445 lv_event_code_t code = lv_event_get_code(e);
446
447 /*Ancestor events will be called during drawing*/
448 if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_POST) {
449 /*Call the ancestor's event handler*/
450 lv_res_t res = lv_obj_event_base(MY_CLASS, e);
451 if(res != LV_RES_OK) return;
452 }
453
454 lv_obj_t * obj = lv_event_get_target(e);
455 lv_img_t * img = (lv_img_t *)obj;
456
457 if(code == LV_EVENT_STYLE_CHANGED) {
458 /*Refresh the file name to refresh the symbol text size*/
459 if(img->src_type == LV_IMG_SRC_SYMBOL) {
460 lv_img_set_src(obj, img->src);
461 }
462 else {
463 /*With transformation it might change*/
464 lv_obj_refresh_ext_draw_size(obj);
465 }
466 }
467 else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
468
469 lv_coord_t * s = lv_event_get_param(e);
470 lv_coord_t transf_zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
471 transf_zoom = ((int32_t)transf_zoom * img->zoom) >> 8;
472
473 lv_coord_t transf_angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
474 transf_angle += img->angle;
475
476 /*If the image has angle provide enough room for the rotated corners*/
477 if(transf_angle || transf_zoom != LV_IMG_ZOOM_NONE) {
478 lv_area_t a;
479 lv_coord_t w = lv_obj_get_width(obj);
480 lv_coord_t h = lv_obj_get_height(obj);
481 _lv_img_buf_get_transformed_area(&a, w, h, transf_angle, transf_zoom, &img->pivot);
482 lv_coord_t pad_ori = *s;
483 *s = LV_MAX(*s, pad_ori - a.x1);
484 *s = LV_MAX(*s, pad_ori - a.y1);
485 *s = LV_MAX(*s, pad_ori + a.x2 - w);
486 *s = LV_MAX(*s, pad_ori + a.y2 - h);
487 }
488 }
489 else if(code == LV_EVENT_HIT_TEST) {
490 lv_hit_test_info_t * info = lv_event_get_param(e);
491 lv_coord_t zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
492 zoom = (zoom * img->zoom) >> 8;
493
494 lv_coord_t angle = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
495 angle += img->angle;
496
497 /*If the object is exactly image sized (not cropped, not mosaic) and transformed
498 *perform hit test on its transformed area*/
499 if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) &&
500 (zoom != LV_IMG_ZOOM_NONE || angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) {
501
502 lv_coord_t w = lv_obj_get_width(obj);
503 lv_coord_t h = lv_obj_get_height(obj);
504 lv_area_t coords;
505 _lv_img_buf_get_transformed_area(&coords, w, h, angle, zoom, &img->pivot);
506 coords.x1 += obj->coords.x1;
507 coords.y1 += obj->coords.y1;
508 coords.x2 += obj->coords.x1;
509 coords.y2 += obj->coords.y1;
510
511 info->res = _lv_area_is_point_on(&coords, info->point, 0);
512 }
513 else {
514 lv_area_t a;
515 lv_obj_get_click_area(obj, &a);
516 info->res = _lv_area_is_point_on(&a, info->point, 0);
517 }
518 }
519 else if(code == LV_EVENT_GET_SELF_SIZE) {
520 lv_point_t * p = lv_event_get_param(e);
521 if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) {
522 *p = lv_img_get_transformed_size(obj);
523 }
524 else {
525 p->x = img->w;
526 p->y = img->h;
527 }
528 }
529 else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) {
530 draw_img(e);
531 }
532 }
533
draw_img(lv_event_t * e)534 static void draw_img(lv_event_t * e)
535 {
536 lv_event_code_t code = lv_event_get_code(e);
537 lv_obj_t * obj = lv_event_get_target(e);
538 lv_img_t * img = (lv_img_t *)obj;
539 if(code == LV_EVENT_COVER_CHECK) {
540 lv_cover_check_info_t * info = lv_event_get_param(e);
541 if(info->res == LV_COVER_RES_MASKED) return;
542 if(img->src_type == LV_IMG_SRC_UNKNOWN || img->src_type == LV_IMG_SRC_SYMBOL) {
543 info->res = LV_COVER_RES_NOT_COVER;
544 return;
545 }
546
547 /*Non true color format might have "holes"*/
548 if(img->cf != LV_IMG_CF_TRUE_COLOR && img->cf != LV_IMG_CF_RAW) {
549 info->res = LV_COVER_RES_NOT_COVER;
550 return;
551 }
552
553 /*With not LV_OPA_COVER images can't cover an area */
554 if(lv_obj_get_style_img_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) {
555 info->res = LV_COVER_RES_NOT_COVER;
556 return;
557 }
558
559 int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
560 angle_final += img->angle;
561
562 if(angle_final != 0) {
563 info->res = LV_COVER_RES_NOT_COVER;
564 return;
565 }
566
567 int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
568 zoom_final = (zoom_final * img->zoom) >> 8;
569
570 const lv_area_t * clip_area = lv_event_get_param(e);
571 if(zoom_final == LV_IMG_ZOOM_NONE) {
572 if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) {
573 info->res = LV_COVER_RES_NOT_COVER;
574 return;
575 }
576 }
577 else {
578 lv_area_t a;
579 _lv_img_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, zoom_final, &img->pivot);
580 a.x1 += obj->coords.x1;
581 a.y1 += obj->coords.y1;
582 a.x2 += obj->coords.x1;
583 a.y2 += obj->coords.y1;
584
585 if(_lv_area_is_in(clip_area, &a, 0) == false) {
586 info->res = LV_COVER_RES_NOT_COVER;
587 return;
588 }
589 }
590 }
591 else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST) {
592
593 int32_t zoom_final = lv_obj_get_style_transform_zoom(obj, LV_PART_MAIN);
594 zoom_final = (zoom_final * img->zoom) >> 8;
595
596 int32_t angle_final = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
597 angle_final += img->angle;
598
599 lv_coord_t obj_w = lv_obj_get_width(obj);
600 lv_coord_t obj_h = lv_obj_get_height(obj);
601
602 lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
603 lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width;
604 lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width;
605 lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width;
606 lv_coord_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width;
607
608 lv_point_t bg_pivot;
609 bg_pivot.x = img->pivot.x + pleft;
610 bg_pivot.y = img->pivot.y + ptop;
611 lv_area_t bg_coords;
612
613 if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) {
614 /*Object size equals to transformed image size*/
615 lv_obj_get_coords(obj, &bg_coords);
616 }
617 else {
618 _lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h,
619 angle_final, zoom_final, &bg_pivot);
620
621 /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/
622 bg_coords.x1 += obj->coords.x1;
623 bg_coords.y1 += obj->coords.y1;
624 bg_coords.x2 += obj->coords.x1;
625 bg_coords.y2 += obj->coords.y1;
626 }
627
628 lv_area_t ori_coords;
629 lv_area_copy(&ori_coords, &obj->coords);
630 lv_area_copy(&obj->coords, &bg_coords);
631
632 lv_res_t res = lv_obj_event_base(MY_CLASS, e);
633 if(res != LV_RES_OK) return;
634
635 lv_area_copy(&obj->coords, &ori_coords);
636
637 if(code == LV_EVENT_DRAW_MAIN) {
638 if(img->h == 0 || img->w == 0) return;
639 if(zoom_final == 0) return;
640
641 lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
642
643 lv_area_t img_max_area;
644 lv_area_copy(&img_max_area, &obj->coords);
645
646 lv_point_t img_size_final = lv_img_get_transformed_size(obj);
647
648 if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) {
649 img_max_area.x1 -= ((img->w - img_size_final.x) + 1) / 2;
650 img_max_area.x2 -= ((img->w - img_size_final.x) + 1) / 2;
651 img_max_area.y1 -= ((img->h - img_size_final.y) + 1) / 2;
652 img_max_area.y2 -= ((img->h - img_size_final.y) + 1) / 2;
653 }
654 else {
655 img_max_area.x2 = img_max_area.x1 + lv_area_get_width(&bg_coords) - 1;
656 img_max_area.y2 = img_max_area.y1 + lv_area_get_height(&bg_coords) - 1;
657 }
658
659 img_max_area.x1 += pleft;
660 img_max_area.y1 += ptop;
661 img_max_area.x2 -= pright;
662 img_max_area.y2 -= pbottom;
663
664 if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_VARIABLE) {
665 lv_draw_img_dsc_t img_dsc;
666 lv_draw_img_dsc_init(&img_dsc);
667 lv_obj_init_draw_img_dsc(obj, LV_PART_MAIN, &img_dsc);
668
669 img_dsc.zoom = zoom_final;
670 img_dsc.angle = angle_final;
671 img_dsc.pivot.x = img->pivot.x;
672 img_dsc.pivot.y = img->pivot.y;
673 img_dsc.antialias = img->antialias;
674
675 lv_area_t img_clip_area;
676 img_clip_area.x1 = bg_coords.x1 + pleft;
677 img_clip_area.y1 = bg_coords.y1 + ptop;
678 img_clip_area.x2 = bg_coords.x2 - pright;
679 img_clip_area.y2 = bg_coords.y2 - pbottom;
680 const lv_area_t * clip_area_ori = draw_ctx->clip_area;
681
682 if(!_lv_area_intersect(&img_clip_area, draw_ctx->clip_area, &img_clip_area)) return;
683 draw_ctx->clip_area = &img_clip_area;
684
685 lv_area_t coords_tmp;
686 coords_tmp.y1 = img_max_area.y1 + img->offset.y;
687 if(coords_tmp.y1 > img_max_area.y1) coords_tmp.y1 -= img->h;
688 coords_tmp.y2 = coords_tmp.y1 + img->h - 1;
689
690 for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img_size_final.y, coords_tmp.y2 += img_size_final.y) {
691 coords_tmp.x1 = img_max_area.x1 + img->offset.x;
692 if(coords_tmp.x1 > img_max_area.x1) coords_tmp.x1 -= img->w;
693 coords_tmp.x2 = coords_tmp.x1 + img->w - 1;
694
695 for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img_size_final.x, coords_tmp.x2 += img_size_final.x) {
696 lv_draw_img(draw_ctx, &img_dsc, &coords_tmp, img->src);
697 }
698 }
699 draw_ctx->clip_area = clip_area_ori;
700 }
701 else if(img->src_type == LV_IMG_SRC_SYMBOL) {
702 lv_draw_label_dsc_t label_dsc;
703 lv_draw_label_dsc_init(&label_dsc);
704 lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc);
705
706 lv_draw_label(draw_ctx, &label_dsc, &obj->coords, img->src, NULL);
707 }
708 else {
709 /*Trigger the error handler of image draw*/
710 LV_LOG_WARN("draw_img: image source type is unknown");
711 lv_draw_img(draw_ctx, NULL, &obj->coords, NULL);
712 }
713 }
714 }
715 }
716
717 #endif
718