1 /**
2 * @file lv_gpu_d2_draw_label.c
3 *
4 * @description HAL layer for display driver
5 *
6 */
7
8 /*********************
9 * INCLUDES
10 *********************/
11 #include "../../draw/lv_draw_label.h"
12 #include "../../misc/lv_assert.h"
13 #include "../../core/lv_refr.h"
14 #include "lv_gpu_d2_ra6m3.h"
15
16 #if LV_USE_GPU_RA6M3_G2D
17 #include LV_GPU_RA6M3_G2D_INCLUDE
18
19 /**********************
20 * STATIC VARIABLES
21 **********************/
22
23 /**********************
24 * GLOBAL VARIABLES
25 **********************/
26 extern const uint8_t _lv_bpp1_opa_table[2];
27 extern const uint8_t _lv_bpp2_opa_table[4];
28 extern const uint8_t _lv_bpp4_opa_table[16];
29 extern const uint8_t _lv_bpp8_opa_table[256];
30
31 /**********************
32 * MACROS
33 **********************/
34
35 /**********************
36 * GLOBAL FUNCTIONS
37 **********************/
38
39 /**********************
40 * STATIC FUNCTIONS
41 **********************/
42
draw_letter_normal(lv_draw_ctx_t * draw_ctx,const lv_draw_label_dsc_t * dsc,const lv_point_t * pos,lv_font_glyph_dsc_t * g,const uint8_t * map_p)43 static void LV_ATTRIBUTE_FAST_MEM draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
44 const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
45 {
46
47 const uint8_t * bpp_opa_table_p;
48 uint32_t bitmask_init;
49 uint32_t bitmask;
50 uint32_t bpp = g->bpp;
51 lv_opa_t opa = dsc->opa;
52 uint32_t shades;
53 if(bpp == 3) bpp = 4;
54
55 #if LV_USE_IMGFONT
56 if(bpp == LV_IMGFONT_BPP) { //is imgfont
57 lv_area_t fill_area;
58 fill_area.x1 = pos->x;
59 fill_area.y1 = pos->y;
60 fill_area.x2 = pos->x + g->box_w - 1;
61 fill_area.y2 = pos->y + g->box_h - 1;
62 lv_draw_img_dsc_t img_dsc;
63 lv_draw_img_dsc_init(&img_dsc);
64 img_dsc.angle = 0;
65 img_dsc.zoom = LV_IMG_ZOOM_NONE;
66 img_dsc.opa = dsc->opa;
67 img_dsc.blend_mode = dsc->blend_mode;
68 lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
69 return;
70 }
71 #endif
72
73 switch(bpp) {
74 case 1:
75 bpp_opa_table_p = _lv_bpp1_opa_table;
76 bitmask_init = 0x80;
77 shades = 2;
78 break;
79 case 2:
80 bpp_opa_table_p = _lv_bpp2_opa_table;
81 bitmask_init = 0xC0;
82 shades = 4;
83 break;
84 case 4:
85 bpp_opa_table_p = _lv_bpp4_opa_table;
86 bitmask_init = 0xF0;
87 shades = 16;
88 break;
89 case 8:
90 bpp_opa_table_p = _lv_bpp8_opa_table;
91 bitmask_init = 0xFF;
92 shades = 256;
93 break; /*No opa table, pixel value will be used directly*/
94 default:
95 LV_LOG_WARN("lv_draw_letter: invalid bpp");
96 return; /*Invalid bpp. Can't render the letter*/
97 }
98
99 static lv_opa_t opa_table[256];
100 static lv_opa_t prev_opa = LV_OPA_TRANSP;
101 static uint32_t prev_bpp = 0;
102 if(opa < LV_OPA_MAX) {
103 if(prev_opa != opa || prev_bpp != bpp) {
104 uint32_t i;
105 for(i = 0; i < shades; i++) {
106 opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
107 }
108 }
109 bpp_opa_table_p = opa_table;
110 prev_opa = opa;
111 prev_bpp = bpp;
112 }
113
114 int32_t col, row;
115 int32_t box_w = g->box_w;
116 int32_t box_h = g->box_h;
117 int32_t width_bit = box_w * bpp; /*Letter width in bits*/
118
119 /*Calculate the col/row start/end on the map*/
120 int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
121 int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
122 int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
123 int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
124
125 /*Move on the map too*/
126 uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
127 map_p += bit_ofs >> 3;
128
129 uint8_t letter_px;
130 uint32_t col_bit;
131 col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
132
133 lv_draw_sw_blend_dsc_t blend_dsc;
134 lv_memset_00(&blend_dsc, sizeof(blend_dsc));
135 blend_dsc.color = dsc->color;
136 blend_dsc.opa = LV_OPA_COVER;
137 blend_dsc.blend_mode = dsc->blend_mode;
138
139 lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
140 uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
141 lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
142 blend_dsc.mask_buf = mask_buf;
143 int32_t mask_p = 0;
144
145 lv_area_t fill_area;
146 fill_area.x1 = col_start + pos->x;
147 fill_area.x2 = col_end + pos->x - 1;
148 fill_area.y1 = row_start + pos->y;
149 fill_area.y2 = fill_area.y1;
150 #if LV_DRAW_COMPLEX
151 lv_coord_t fill_w = lv_area_get_width(&fill_area);
152 lv_area_t mask_area;
153 lv_area_copy(&mask_area, &fill_area);
154 mask_area.y2 = mask_area.y1 + row_end;
155 bool mask_any = lv_draw_mask_is_any(&mask_area);
156 #endif
157 blend_dsc.blend_area = &fill_area;
158 blend_dsc.mask_area = &fill_area;
159
160 uint32_t col_bit_max = 8 - bpp;
161 uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
162
163 for(row = row_start ; row < row_end; row++) {
164 #if LV_DRAW_COMPLEX
165 int32_t mask_p_start = mask_p;
166 #endif
167 bitmask = bitmask_init >> col_bit;
168 for(col = col_start; col < col_end; col++) {
169 /*Load the pixel's opacity into the mask*/
170 letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
171 if(letter_px) {
172 mask_buf[mask_p] = bpp_opa_table_p[letter_px];
173 }
174 else {
175 mask_buf[mask_p] = 0;
176 }
177
178 /*Go to the next column*/
179 if(col_bit < col_bit_max) {
180 col_bit += bpp;
181 bitmask = bitmask >> bpp;
182 }
183 else {
184 col_bit = 0;
185 bitmask = bitmask_init;
186 map_p++;
187 }
188
189 /*Next mask byte*/
190 mask_p++;
191 }
192
193 #if LV_DRAW_COMPLEX
194 /*Apply masks if any*/
195 if(mask_any) {
196 blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
197 fill_w);
198 if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
199 lv_memset_00(mask_buf + mask_p_start, fill_w);
200 }
201 }
202 #endif
203
204 if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
205 fill_area.y2 ++;
206 }
207 else {
208 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
209 lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
210
211 fill_area.y1 = fill_area.y2 + 1;
212 fill_area.y2 = fill_area.y1;
213 mask_p = 0;
214 }
215
216 col_bit += col_bit_row_ofs;
217 map_p += (col_bit >> 3);
218 col_bit = col_bit & 0x7;
219 }
220
221 /*Flush the last part*/
222 if(fill_area.y1 != fill_area.y2) {
223 fill_area.y2--;
224 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
225 lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
226 mask_p = 0;
227 }
228
229 lv_mem_buf_release(mask_buf);
230 }
231
lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx,const lv_draw_label_dsc_t * dsc,const lv_point_t * pos_p,uint32_t letter)232 void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
233 uint32_t letter)
234 {
235 const lv_font_t * font_p = dsc->font;
236
237 lv_opa_t opa = dsc->opa;
238 if(opa < LV_OPA_MIN) return;
239 if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
240
241 if(font_p == NULL) {
242 LV_LOG_WARN("lv_draw_letter: font is NULL");
243 return;
244 }
245
246 lv_font_glyph_dsc_t g;
247 bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
248 if(g_ret == false) {
249 /*Add warning if the dsc is not found
250 *but do not print warning for non printable ASCII chars (e.g. '\n')*/
251 if(letter >= 0x20 &&
252 letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
253 letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
254 LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
255 }
256 return;
257 }
258
259 /*Don't draw anything if the character is empty. E.g. space*/
260 if((g.box_h == 0) || (g.box_w == 0)) return;
261
262 lv_point_t gpos;
263 gpos.x = pos_p->x + g.ofs_x;
264 gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
265
266 /*If the letter is completely out of mask don't draw it*/
267 if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
268 gpos.x > draw_ctx->clip_area->x2 ||
269 gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
270 gpos.y > draw_ctx->clip_area->y2) {
271 return;
272 }
273
274 const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter);
275 if(map_p == NULL) {
276 LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
277 return;
278 }
279
280 if(font_p->subpx) {
281 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
282 draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode);
283 #else
284 LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
285 #endif
286 }
287 else {
288 draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p);
289 }
290 }
291
292 #endif
293