1 /**
2 * @file lv_draw_sw_letter.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_draw_sw.h"
10 #include "../../hal/lv_hal_disp.h"
11 #include "../../misc/lv_math.h"
12 #include "../../misc/lv_assert.h"
13 #include "../../misc/lv_area.h"
14 #include "../../misc/lv_style.h"
15 #include "../../font/lv_font.h"
16 #include "../../core/lv_refr.h"
17
18 /*********************
19 * DEFINES
20 *********************/
21
22 /**********************
23 * TYPEDEFS
24 **********************/
25
26 /**********************
27 * STATIC PROTOTYPES
28 **********************/
29
30 static void /* LV_ATTRIBUTE_FAST_MEM */ draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
31 const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p);
32
33 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
34 static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos,
35 lv_font_glyph_dsc_t * g, const uint8_t * map_p);
36 #endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/
37
38 /**********************
39 * STATIC VARIABLES
40 **********************/
41
42 /**********************
43 * GLOBAL VARIABLES
44 **********************/
45
46 const uint8_t _lv_bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
47 const uint8_t _lv_bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
48
49 const uint8_t _lv_bpp3_opa_table[8] = {0, 36, 73, 109, /*Opacity mapping with bpp = 3*/
50 146, 182, 219, 255
51 };
52
53 const uint8_t _lv_bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
54 68, 85, 102, 119,
55 136, 153, 170, 187,
56 204, 221, 238, 255
57 };
58
59 const uint8_t _lv_bpp8_opa_table[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
60 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
61 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
62 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
63 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
65 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
66 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
67 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
68 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
69 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
70 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
71 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
72 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
73 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
74 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
75 };
76
77 /**********************
78 * MACROS
79 **********************/
80
81 /**********************
82 * GLOBAL FUNCTIONS
83 **********************/
84
85 /**
86 * Draw a letter in the Virtual Display Buffer
87 * @param pos_p left-top coordinate of the latter
88 * @param mask_p the letter will be drawn only on this area (truncated to draw_buf area)
89 * @param font_p pointer to font
90 * @param letter a letter to draw
91 * @param color color of letter
92 * @param opa opacity of letter (0..255)
93 */
lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx,const lv_draw_label_dsc_t * dsc,const lv_point_t * pos_p,uint32_t letter)94 void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
95 uint32_t letter)
96 {
97 lv_font_glyph_dsc_t g;
98 bool g_ret = lv_font_get_glyph_dsc(dsc->font, &g, letter, '\0');
99 if(g_ret == false) {
100 /*Add warning if the dsc is not found
101 *but do not print warning for non printable ASCII chars (e.g. '\n')*/
102 if(letter >= 0x20 &&
103 letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
104 letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
105 LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter);
106
107 #if LV_USE_FONT_PLACEHOLDER
108 /* draw placeholder */
109 lv_area_t glyph_coords;
110 lv_draw_rect_dsc_t glyph_dsc;
111 lv_coord_t begin_x = pos_p->x + g.ofs_x;
112 lv_coord_t begin_y = pos_p->y + g.ofs_y;
113 lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h);
114 lv_draw_rect_dsc_init(&glyph_dsc);
115 glyph_dsc.bg_opa = LV_OPA_MIN;
116 glyph_dsc.outline_opa = LV_OPA_MIN;
117 glyph_dsc.shadow_opa = LV_OPA_MIN;
118 glyph_dsc.bg_img_opa = LV_OPA_MIN;
119 glyph_dsc.border_color = dsc->color;
120 glyph_dsc.border_width = 1;
121 draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords);
122 #endif
123 }
124 return;
125 }
126
127 /*Don't draw anything if the character is empty. E.g. space*/
128 if((g.box_h == 0) || (g.box_w == 0)) return;
129
130 lv_point_t gpos;
131 gpos.x = pos_p->x + g.ofs_x;
132 gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
133
134 /*If the letter is completely out of mask don't draw it*/
135 if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
136 gpos.x > draw_ctx->clip_area->x2 ||
137 gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
138 gpos.y > draw_ctx->clip_area->y2) {
139 return;
140 }
141
142 const uint8_t * map_p = lv_font_get_glyph_bitmap(g.resolved_font, letter);
143 if(map_p == NULL) {
144 LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
145 return;
146 }
147
148 if(g.resolved_font->subpx) {
149 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
150 draw_letter_subpx(draw_ctx, dsc, &gpos, &g, map_p);
151 #else
152 LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
153 #endif
154 }
155 else {
156 draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p);
157 }
158 }
159
160 /**********************
161 * STATIC FUNCTIONS
162 **********************/
163
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)164 static void LV_ATTRIBUTE_FAST_MEM draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
165 const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
166 {
167
168 const uint8_t * bpp_opa_table_p;
169 uint32_t bitmask_init;
170 uint32_t bitmask;
171 uint32_t bpp = g->bpp;
172 lv_opa_t opa = dsc->opa;
173 uint32_t shades;
174 if(bpp == 3) bpp = 4;
175
176 #if LV_USE_IMGFONT
177 if(bpp == LV_IMGFONT_BPP) { //is imgfont
178 lv_area_t fill_area;
179 fill_area.x1 = pos->x;
180 fill_area.y1 = pos->y;
181 fill_area.x2 = pos->x + g->box_w - 1;
182 fill_area.y2 = pos->y + g->box_h - 1;
183 lv_draw_img_dsc_t img_dsc;
184 lv_draw_img_dsc_init(&img_dsc);
185 img_dsc.angle = 0;
186 img_dsc.zoom = LV_IMG_ZOOM_NONE;
187 img_dsc.opa = dsc->opa;
188 img_dsc.blend_mode = dsc->blend_mode;
189 lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
190 return;
191 }
192 #endif
193
194 switch(bpp) {
195 case 1:
196 bpp_opa_table_p = _lv_bpp1_opa_table;
197 bitmask_init = 0x80;
198 shades = 2;
199 break;
200 case 2:
201 bpp_opa_table_p = _lv_bpp2_opa_table;
202 bitmask_init = 0xC0;
203 shades = 4;
204 break;
205 case 4:
206 bpp_opa_table_p = _lv_bpp4_opa_table;
207 bitmask_init = 0xF0;
208 shades = 16;
209 break;
210 case 8:
211 bpp_opa_table_p = _lv_bpp8_opa_table;
212 bitmask_init = 0xFF;
213 shades = 256;
214 break; /*No opa table, pixel value will be used directly*/
215 default:
216 LV_LOG_WARN("lv_draw_letter: invalid bpp");
217 return; /*Invalid bpp. Can't render the letter*/
218 }
219
220 static lv_opa_t opa_table[256];
221 static lv_opa_t prev_opa = LV_OPA_TRANSP;
222 static uint32_t prev_bpp = 0;
223 if(opa < LV_OPA_MAX) {
224 if(prev_opa != opa || prev_bpp != bpp) {
225 uint32_t i;
226 for(i = 0; i < shades; i++) {
227 opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
228 }
229 }
230 bpp_opa_table_p = opa_table;
231 prev_opa = opa;
232 prev_bpp = bpp;
233 }
234
235 int32_t col, row;
236 int32_t box_w = g->box_w;
237 int32_t box_h = g->box_h;
238 int32_t width_bit = box_w * bpp; /*Letter width in bits*/
239
240 /*Calculate the col/row start/end on the map*/
241 int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
242 int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
243 int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
244 int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
245
246 /*Move on the map too*/
247 uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
248 map_p += bit_ofs >> 3;
249
250 uint8_t letter_px;
251 uint32_t col_bit;
252 col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
253
254 lv_draw_sw_blend_dsc_t blend_dsc;
255 lv_memset_00(&blend_dsc, sizeof(blend_dsc));
256 blend_dsc.color = dsc->color;
257 blend_dsc.opa = dsc->opa;
258 blend_dsc.blend_mode = dsc->blend_mode;
259
260 lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
261 uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
262 lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
263 blend_dsc.mask_buf = mask_buf;
264 int32_t mask_p = 0;
265
266 lv_area_t fill_area;
267 fill_area.x1 = col_start + pos->x;
268 fill_area.x2 = col_end + pos->x - 1;
269 fill_area.y1 = row_start + pos->y;
270 fill_area.y2 = fill_area.y1;
271 #if LV_DRAW_COMPLEX
272 lv_coord_t fill_w = lv_area_get_width(&fill_area);
273 lv_area_t mask_area;
274 lv_area_copy(&mask_area, &fill_area);
275 mask_area.y2 = mask_area.y1 + row_end;
276 bool mask_any = lv_draw_mask_is_any(&mask_area);
277 #endif
278 blend_dsc.blend_area = &fill_area;
279 blend_dsc.mask_area = &fill_area;
280
281 uint32_t col_bit_max = 8 - bpp;
282 uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
283
284 for(row = row_start ; row < row_end; row++) {
285 #if LV_DRAW_COMPLEX
286 int32_t mask_p_start = mask_p;
287 #endif
288 bitmask = bitmask_init >> col_bit;
289 for(col = col_start; col < col_end; col++) {
290 /*Load the pixel's opacity into the mask*/
291 letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
292 if(letter_px) {
293 mask_buf[mask_p] = bpp_opa_table_p[letter_px];
294 }
295 else {
296 mask_buf[mask_p] = 0;
297 }
298
299 /*Go to the next column*/
300 if(col_bit < col_bit_max) {
301 col_bit += bpp;
302 bitmask = bitmask >> bpp;
303 }
304 else {
305 col_bit = 0;
306 bitmask = bitmask_init;
307 map_p++;
308 }
309
310 /*Next mask byte*/
311 mask_p++;
312 }
313
314 #if LV_DRAW_COMPLEX
315 /*Apply masks if any*/
316 if(mask_any) {
317 blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
318 fill_w);
319 if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
320 lv_memset_00(mask_buf + mask_p_start, fill_w);
321 }
322 }
323 #endif
324
325 if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
326 fill_area.y2 ++;
327 }
328 else {
329 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
330 lv_draw_sw_blend(draw_ctx, &blend_dsc);
331
332 fill_area.y1 = fill_area.y2 + 1;
333 fill_area.y2 = fill_area.y1;
334 mask_p = 0;
335 }
336
337 col_bit += col_bit_row_ofs;
338 map_p += (col_bit >> 3);
339 col_bit = col_bit & 0x7;
340 }
341
342 /*Flush the last part*/
343 if(fill_area.y1 != fill_area.y2) {
344 fill_area.y2--;
345 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
346 lv_draw_sw_blend(draw_ctx, &blend_dsc);
347 mask_p = 0;
348 }
349
350 lv_mem_buf_release(mask_buf);
351 }
352
353 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
draw_letter_subpx(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)354 static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos,
355 lv_font_glyph_dsc_t * g, const uint8_t * map_p)
356 {
357 const uint8_t * bpp_opa_table;
358 uint32_t bitmask_init;
359 uint32_t bitmask;
360 uint32_t bpp = g->bpp;
361 lv_opa_t opa = dsc->opa;
362 if(bpp == 3) bpp = 4;
363
364 switch(bpp) {
365 case 1:
366 bpp_opa_table = _lv_bpp1_opa_table;
367 bitmask_init = 0x80;
368 break;
369 case 2:
370 bpp_opa_table = _lv_bpp2_opa_table;
371 bitmask_init = 0xC0;
372 break;
373 case 4:
374 bpp_opa_table = _lv_bpp4_opa_table;
375 bitmask_init = 0xF0;
376 break;
377 case 8:
378 bpp_opa_table = _lv_bpp8_opa_table;
379 bitmask_init = 0xFF;
380 break; /*No opa table, pixel value will be used directly*/
381 default:
382 LV_LOG_WARN("lv_draw_letter: invalid bpp not found");
383 return; /*Invalid bpp. Can't render the letter*/
384 }
385
386 int32_t col, row;
387
388 int32_t box_w = g->box_w;
389 int32_t box_h = g->box_h;
390 int32_t width_bit = box_w * bpp; /*Letter width in bits*/
391
392 /*Calculate the col/row start/end on the map*/
393 int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : (draw_ctx->clip_area->x1 - pos->x) * 3;
394 int32_t col_end = pos->x + box_w / 3 <= draw_ctx->clip_area->x2 ? box_w : (draw_ctx->clip_area->x2 - pos->x + 1) * 3;
395 int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
396 int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
397
398 /*Move on the map too*/
399 int32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
400 map_p += bit_ofs >> 3;
401
402 uint8_t letter_px;
403 lv_opa_t px_opa;
404 int32_t col_bit;
405 col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
406
407 lv_area_t map_area;
408 map_area.x1 = col_start / 3 + pos->x;
409 map_area.x2 = col_end / 3 + pos->x - 1;
410 map_area.y1 = row_start + pos->y;
411 map_area.y2 = map_area.y1;
412
413 if(map_area.x2 <= map_area.x1) return;
414
415 lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
416 int32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : g->box_w * g->box_h;
417 lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
418 int32_t mask_p = 0;
419
420 lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
421
422 int32_t dest_buf_stride = lv_area_get_width(draw_ctx->buf_area);
423 lv_color_t * dest_buf_tmp = draw_ctx->buf;
424
425 /*Set a pointer on draw_buf to the first pixel of the letter*/
426 dest_buf_tmp += ((pos->y - draw_ctx->buf_area->y1) * dest_buf_stride) + pos->x - draw_ctx->buf_area->x1;
427
428 /*If the letter is partially out of mask the move there on draw_buf*/
429 dest_buf_tmp += (row_start * dest_buf_stride) + col_start / 3;
430
431 lv_area_t mask_area;
432 lv_area_copy(&mask_area, &map_area);
433 mask_area.y2 = mask_area.y1 + row_end;
434 bool mask_any = lv_draw_mask_is_any(&map_area);
435 uint8_t font_rgb[3];
436
437 lv_color_t color = dsc->color;
438 #if LV_COLOR_16_SWAP == 0
439 uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue};
440 #else
441 uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue};
442 #endif
443
444 lv_draw_sw_blend_dsc_t blend_dsc;
445 lv_memset_00(&blend_dsc, sizeof(blend_dsc));
446 blend_dsc.blend_area = &map_area;
447 blend_dsc.mask_area = &map_area;
448 blend_dsc.src_buf = color_buf;
449 blend_dsc.mask_buf = mask_buf;
450 blend_dsc.opa = opa;
451 blend_dsc.blend_mode = dsc->blend_mode;
452
453 for(row = row_start ; row < row_end; row++) {
454 uint32_t subpx_cnt = 0;
455 bitmask = bitmask_init >> col_bit;
456 int32_t mask_p_start = mask_p;
457
458 for(col = col_start; col < col_end; col++) {
459 /*Load the pixel's opacity into the mask*/
460 letter_px = (*map_p & bitmask) >> (8 - col_bit - bpp);
461 if(letter_px != 0) {
462 if(opa >= LV_OPA_MAX) {
463 px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px];
464 }
465 else {
466 px_opa = bpp == 8 ? (uint32_t)((uint32_t)letter_px * opa) >> 8
467 : (uint32_t)((uint32_t)bpp_opa_table[letter_px] * opa) >> 8;
468 }
469 }
470 else {
471 px_opa = 0;
472 }
473
474 font_rgb[subpx_cnt] = px_opa;
475
476 subpx_cnt ++;
477 if(subpx_cnt == 3) {
478 subpx_cnt = 0;
479
480 lv_color_t res_color;
481 #if LV_COLOR_16_SWAP == 0
482 uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red, dest_buf_tmp->ch.green, dest_buf_tmp->ch.blue};
483 #else
484 uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red,
485 (dest_buf_tmp->ch.green_h << 3) + dest_buf_tmp->ch.green_l,
486 dest_buf_tmp->ch.blue
487 };
488 #endif
489
490 #if LV_FONT_SUBPX_BGR
491 res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8;
492 res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8;
493 #else
494 res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
495 res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
496 #endif
497
498 #if LV_COLOR_16_SWAP == 0
499 res_color.ch.green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
500 #else
501 uint8_t green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
502 res_color.ch.green_h = green >> 3;
503 res_color.ch.green_l = green & 0x7;
504 #endif
505
506 #if LV_COLOR_DEPTH == 32
507 res_color.ch.alpha = 0xff;
508 #endif
509
510 if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP;
511 else mask_buf[mask_p] = LV_OPA_COVER;
512 color_buf[mask_p] = res_color;
513
514 /*Next mask byte*/
515 mask_p++;
516 dest_buf_tmp++;
517 }
518
519 /*Go to the next column*/
520 if(col_bit < (int32_t)(8 - bpp)) {
521 col_bit += bpp;
522 bitmask = bitmask >> bpp;
523 }
524 else {
525 col_bit = 0;
526 bitmask = bitmask_init;
527 map_p++;
528 }
529 }
530
531 /*Apply masks if any*/
532 if(mask_any) {
533 blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2,
534 lv_area_get_width(&map_area));
535 if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
536 lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&map_area));
537 }
538 }
539
540 if((int32_t) mask_p + (col_end - col_start) < mask_buf_size) {
541 map_area.y2 ++;
542 }
543 else {
544 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
545 lv_draw_sw_blend(draw_ctx, &blend_dsc);
546
547 map_area.y1 = map_area.y2 + 1;
548 map_area.y2 = map_area.y1;
549 mask_p = 0;
550 }
551
552 col_bit += ((box_w - col_end) + col_start) * bpp;
553
554 map_p += (col_bit >> 3);
555 col_bit = col_bit & 0x7;
556
557 /*Next row in draw_buf*/
558 dest_buf_tmp += dest_buf_stride - (col_end - col_start) / 3;
559 }
560
561 /*Flush the last part*/
562 if(map_area.y1 != map_area.y2) {
563 map_area.y2--;
564 blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
565 lv_draw_sw_blend(draw_ctx, &blend_dsc);
566 }
567
568 lv_mem_buf_release(mask_buf);
569 lv_mem_buf_release(color_buf);
570 }
571 #endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/
572