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