1 /**
2  * @file lv_draw_vg_lite_img.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "../../misc/lv_area_private.h"
11 #include "../lv_image_decoder_private.h"
12 #include "../lv_draw_image_private.h"
13 #include "../lv_draw_private.h"
14 #include "lv_draw_vg_lite.h"
15 
16 #if LV_USE_DRAW_VG_LITE
17 
18 #include "lv_draw_vg_lite_type.h"
19 #include "lv_vg_lite_decoder.h"
20 #include "lv_vg_lite_path.h"
21 #include "lv_vg_lite_pending.h"
22 #include "lv_vg_lite_utils.h"
23 
24 /*********************
25  *      DEFINES
26  *********************/
27 
28 /**********************
29  *      TYPEDEFS
30  **********************/
31 
32 /**********************
33  *  STATIC PROTOTYPES
34  **********************/
35 
36 /**********************
37  *  STATIC VARIABLES
38  **********************/
39 
40 /**********************
41  *      MACROS
42  **********************/
43 
44 /**********************
45  *   GLOBAL FUNCTIONS
46  **********************/
47 
lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit,const lv_draw_image_dsc_t * dsc,const lv_area_t * coords,bool no_cache)48 void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
49                          const lv_area_t * coords, bool no_cache)
50 {
51     lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
52 
53     /* The coordinates passed in by coords are not transformed,
54      * so the transformed area needs to be calculated once.
55      */
56     lv_area_t image_tf_area;
57     lv_image_buf_get_transformed_area(
58         &image_tf_area,
59         lv_area_get_width(coords),
60         lv_area_get_height(coords),
61         dsc->rotation,
62         dsc->scale_x,
63         dsc->scale_y,
64         &dsc->pivot);
65     lv_area_move(&image_tf_area, coords->x1, coords->y1);
66 
67     lv_area_t clip_area;
68     if(!lv_area_intersect(&clip_area, &image_tf_area, draw_unit->clip_area)) {
69         /*Fully clipped, nothing to do*/
70         return;
71     }
72 
73     LV_PROFILER_DRAW_BEGIN;
74 
75     vg_lite_buffer_t src_buf;
76     lv_image_decoder_dsc_t decoder_dsc;
77 
78     /* if not support blend normal, premultiply alpha */
79     bool premultiply = !lv_vg_lite_support_blend_normal();
80     if(!lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->src, no_cache, premultiply)) {
81         LV_PROFILER_DRAW_END;
82         return;
83     }
84 
85     vg_lite_color_t color = lv_vg_lite_image_recolor(&src_buf, dsc);
86 
87     /* convert the blend mode to vg-lite blend mode, considering the premultiplied alpha */
88     bool has_pre_mul = lv_draw_buf_has_flag(decoder_dsc.decoded, LV_IMAGE_FLAGS_PREMULTIPLIED);
89     vg_lite_blend_t blend = lv_vg_lite_blend_mode(dsc->blend_mode, has_pre_mul);
90 
91     /* original image matrix */
92     vg_lite_matrix_t image_matrix;
93     vg_lite_identity(&image_matrix);
94     lv_vg_lite_image_matrix(&image_matrix, coords->x1, coords->y1, dsc);
95 
96     /* image drawing matrix */
97     vg_lite_matrix_t matrix = u->global_matrix;
98     lv_vg_lite_matrix_multiply(&matrix, &image_matrix);
99 
100     LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf);
101     LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
102     LV_VG_LITE_ASSERT_MATRIX(&matrix);
103 
104     bool no_transform = lv_matrix_is_identity_or_translation((const lv_matrix_t *)&matrix);
105     vg_lite_filter_t filter = no_transform ? VG_LITE_FILTER_POINT : VG_LITE_FILTER_BI_LINEAR;
106 
107     /* If clipping is not required, blit directly */
108     if(lv_area_is_in(&image_tf_area, draw_unit->clip_area, false) && dsc->clip_radius <= 0) {
109         /* rect is used to crop the pixel-aligned padding area */
110         vg_lite_rectangle_t rect = {
111             .x = 0,
112             .y = 0,
113             .width = lv_area_get_width(coords),
114             .height = lv_area_get_height(coords),
115         };
116 
117         LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_blit_rect");
118         LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect(
119                                    &u->target_buffer,
120                                    &src_buf,
121                                    &rect,
122                                    &matrix,
123                                    blend,
124                                    color,
125                                    filter));
126         LV_PROFILER_DRAW_END_TAG("vg_lite_blit_rect");
127     }
128     else {
129         lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
130 
131         /**
132          * When the image is transformed or rounded, create a path around
133          * the image and follow the image_matrix for coordinate transformation
134          */
135         if(!no_transform || dsc->clip_radius) {
136             /* apply the image transform to the path */
137             lv_vg_lite_path_set_transform(path, &image_matrix);
138             lv_vg_lite_path_append_rect(
139                 path,
140                 0, 0,
141                 lv_area_get_width(coords), lv_area_get_height(coords),
142                 dsc->clip_radius);
143             lv_vg_lite_path_set_transform(path, NULL);
144         }
145         else {
146             /* append normal rect to the path */
147             lv_vg_lite_path_append_rect(
148                 path,
149                 clip_area.x1, clip_area.y1,
150                 lv_area_get_width(&clip_area), lv_area_get_height(&clip_area),
151                 0);
152         }
153 
154         lv_vg_lite_path_set_bounding_box_area(path, &clip_area);
155         lv_vg_lite_path_end(path);
156 
157         vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
158         LV_VG_LITE_ASSERT_PATH(vg_lite_path);
159 
160         vg_lite_matrix_t path_matrix = u->global_matrix;
161         LV_VG_LITE_ASSERT_MATRIX(&path_matrix);
162 
163         LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw_pattern");
164         LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
165                                    &u->target_buffer,
166                                    vg_lite_path,
167                                    VG_LITE_FILL_EVEN_ODD,
168                                    &path_matrix,
169                                    &src_buf,
170                                    &matrix,
171                                    blend,
172                                    VG_LITE_PATTERN_COLOR,
173                                    0,
174                                    color,
175                                    filter));
176         LV_PROFILER_DRAW_END_TAG("vg_lite_draw_pattern");
177 
178         lv_vg_lite_path_drop(u, path);
179     }
180 
181     lv_vg_lite_pending_add(u->image_dsc_pending, &decoder_dsc);
182     LV_PROFILER_DRAW_END;
183 }
184 
185 /**********************
186  *   STATIC FUNCTIONS
187  **********************/
188 
189 #endif /*LV_USE_DRAW_VG_LITE*/
190