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