acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_img.c (23560B)

      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 
     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 
     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 width 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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