acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_draw_sw_letter.c (20916B)

      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  */
     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+%" PRIX32, letter);
    107 
    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         }
    123         return;
    124     }
    125 
    126     /*Don't draw anything if the character is empty. E.g. space*/
    127     if((g.box_h == 0) || (g.box_w == 0)) return;
    128 
    129     lv_point_t gpos;
    130     gpos.x = pos_p->x + g.ofs_x;
    131     gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
    132 
    133     /*If the letter is completely out of mask don't draw it*/
    134     if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
    135        gpos.x > draw_ctx->clip_area->x2 ||
    136        gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
    137        gpos.y > draw_ctx->clip_area->y2)  {
    138         return;
    139     }
    140 
    141     const uint8_t * map_p = lv_font_get_glyph_bitmap(g.resolved_font, letter);
    142     if(map_p == NULL) {
    143         LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
    144         return;
    145     }
    146 
    147     if(g.resolved_font->subpx) {
    148 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
    149         draw_letter_subpx(draw_ctx, dsc, &gpos, &g, map_p);
    150 #else
    151         LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
    152 #endif
    153     }
    154     else {
    155         draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p);
    156     }
    157 }
    158 
    159 /**********************
    160  *   STATIC FUNCTIONS
    161  **********************/
    162 
    163 LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
    164                                                      const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
    165 {
    166 
    167     const uint8_t * bpp_opa_table_p;
    168     uint32_t bitmask_init;
    169     uint32_t bitmask;
    170     uint32_t bpp = g->bpp;
    171     lv_opa_t opa = dsc->opa;
    172     uint32_t shades;
    173     if(bpp == 3) bpp = 4;
    174 
    175 #if LV_USE_IMGFONT
    176     if(bpp == LV_IMGFONT_BPP) { //is imgfont
    177         lv_area_t fill_area;
    178         fill_area.x1 = pos->x;
    179         fill_area.y1 = pos->y;
    180         fill_area.x2 = pos->x + g->box_w - 1;
    181         fill_area.y2 = pos->y + g->box_h - 1;
    182         lv_draw_img_dsc_t img_dsc;
    183         lv_draw_img_dsc_init(&img_dsc);
    184         img_dsc.angle = 0;
    185         img_dsc.zoom = LV_IMG_ZOOM_NONE;
    186         img_dsc.opa = dsc->opa;
    187         img_dsc.blend_mode = dsc->blend_mode;
    188         lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
    189         return;
    190     }
    191 #endif
    192 
    193     switch(bpp) {
    194         case 1:
    195             bpp_opa_table_p = _lv_bpp1_opa_table;
    196             bitmask_init  = 0x80;
    197             shades = 2;
    198             break;
    199         case 2:
    200             bpp_opa_table_p = _lv_bpp2_opa_table;
    201             bitmask_init  = 0xC0;
    202             shades = 4;
    203             break;
    204         case 4:
    205             bpp_opa_table_p = _lv_bpp4_opa_table;
    206             bitmask_init  = 0xF0;
    207             shades = 16;
    208             break;
    209         case 8:
    210             bpp_opa_table_p = _lv_bpp8_opa_table;
    211             bitmask_init  = 0xFF;
    212             shades = 256;
    213             break;       /*No opa table, pixel value will be used directly*/
    214         default:
    215             LV_LOG_WARN("lv_draw_letter: invalid bpp");
    216             return; /*Invalid bpp. Can't render the letter*/
    217     }
    218 
    219     static lv_opa_t opa_table[256];
    220     static lv_opa_t prev_opa = LV_OPA_TRANSP;
    221     static uint32_t prev_bpp = 0;
    222     if(opa < LV_OPA_MAX) {
    223         if(prev_opa != opa || prev_bpp != bpp) {
    224             uint32_t i;
    225             for(i = 0; i < shades; i++) {
    226                 opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
    227             }
    228         }
    229         bpp_opa_table_p = opa_table;
    230         prev_opa = opa;
    231         prev_bpp = bpp;
    232     }
    233 
    234     int32_t col, row;
    235     int32_t box_w = g->box_w;
    236     int32_t box_h = g->box_h;
    237     int32_t width_bit = box_w * bpp; /*Letter width in bits*/
    238 
    239     /*Calculate the col/row start/end on the map*/
    240     int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
    241     int32_t col_end   = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
    242     int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
    243     int32_t row_end   = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
    244 
    245     /*Move on the map too*/
    246     uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
    247     map_p += bit_ofs >> 3;
    248 
    249     uint8_t letter_px;
    250     uint32_t col_bit;
    251     col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
    252 
    253     lv_draw_sw_blend_dsc_t blend_dsc;
    254     lv_memset_00(&blend_dsc, sizeof(blend_dsc));
    255     blend_dsc.color = dsc->color;
    256     blend_dsc.opa = dsc->opa;
    257     blend_dsc.blend_mode = dsc->blend_mode;
    258 
    259     lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
    260     uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
    261     lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
    262     blend_dsc.mask_buf = mask_buf;
    263     int32_t mask_p = 0;
    264 
    265     lv_area_t fill_area;
    266     fill_area.x1 = col_start + pos->x;
    267     fill_area.x2 = col_end  + pos->x - 1;
    268     fill_area.y1 = row_start + pos->y;
    269     fill_area.y2 = fill_area.y1;
    270 #if LV_DRAW_COMPLEX
    271     lv_coord_t fill_w = lv_area_get_width(&fill_area);
    272     lv_area_t mask_area;
    273     lv_area_copy(&mask_area, &fill_area);
    274     mask_area.y2 = mask_area.y1 + row_end;
    275     bool mask_any = lv_draw_mask_is_any(&mask_area);
    276 #endif
    277     blend_dsc.blend_area = &fill_area;
    278     blend_dsc.mask_area = &fill_area;
    279 
    280     uint32_t col_bit_max = 8 - bpp;
    281     uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
    282 
    283     for(row = row_start ; row < row_end; row++) {
    284 #if LV_DRAW_COMPLEX
    285         int32_t mask_p_start = mask_p;
    286 #endif
    287         bitmask = bitmask_init >> col_bit;
    288         for(col = col_start; col < col_end; col++) {
    289             /*Load the pixel's opacity into the mask*/
    290             letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
    291             if(letter_px) {
    292                 mask_buf[mask_p] = bpp_opa_table_p[letter_px];
    293             }
    294             else {
    295                 mask_buf[mask_p] = 0;
    296             }
    297 
    298             /*Go to the next column*/
    299             if(col_bit < col_bit_max) {
    300                 col_bit += bpp;
    301                 bitmask = bitmask >> bpp;
    302             }
    303             else {
    304                 col_bit = 0;
    305                 bitmask = bitmask_init;
    306                 map_p++;
    307             }
    308 
    309             /*Next mask byte*/
    310             mask_p++;
    311         }
    312 
    313 #if LV_DRAW_COMPLEX
    314         /*Apply masks if any*/
    315         if(mask_any) {
    316             blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
    317                                                     fill_w);
    318             if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
    319                 lv_memset_00(mask_buf + mask_p_start, fill_w);
    320             }
    321         }
    322 #endif
    323 
    324         if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
    325             fill_area.y2 ++;
    326         }
    327         else {
    328             blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    329             lv_draw_sw_blend(draw_ctx, &blend_dsc);
    330 
    331             fill_area.y1 = fill_area.y2 + 1;
    332             fill_area.y2 = fill_area.y1;
    333             mask_p = 0;
    334         }
    335 
    336         col_bit += col_bit_row_ofs;
    337         map_p += (col_bit >> 3);
    338         col_bit = col_bit & 0x7;
    339     }
    340 
    341     /*Flush the last part*/
    342     if(fill_area.y1 != fill_area.y2) {
    343         fill_area.y2--;
    344         blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    345         lv_draw_sw_blend(draw_ctx, &blend_dsc);
    346         mask_p = 0;
    347     }
    348 
    349     lv_mem_buf_release(mask_buf);
    350 }
    351 
    352 #if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
    353 static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos,
    354                               lv_font_glyph_dsc_t * g, const uint8_t * map_p)
    355 {
    356     const uint8_t * bpp_opa_table;
    357     uint32_t bitmask_init;
    358     uint32_t bitmask;
    359     uint32_t bpp = g->bpp;
    360     lv_opa_t opa = dsc->opa;
    361     if(bpp == 3) bpp = 4;
    362 
    363     switch(bpp) {
    364         case 1:
    365             bpp_opa_table = _lv_bpp1_opa_table;
    366             bitmask_init  = 0x80;
    367             break;
    368         case 2:
    369             bpp_opa_table = _lv_bpp2_opa_table;
    370             bitmask_init  = 0xC0;
    371             break;
    372         case 4:
    373             bpp_opa_table = _lv_bpp4_opa_table;
    374             bitmask_init  = 0xF0;
    375             break;
    376         case 8:
    377             bpp_opa_table = _lv_bpp8_opa_table;
    378             bitmask_init  = 0xFF;
    379             break;       /*No opa table, pixel value will be used directly*/
    380         default:
    381             LV_LOG_WARN("lv_draw_letter: invalid bpp not found");
    382             return; /*Invalid bpp. Can't render the letter*/
    383     }
    384 
    385     int32_t col, row;
    386 
    387     int32_t box_w = g->box_w;
    388     int32_t box_h = g->box_h;
    389     int32_t width_bit = box_w * bpp; /*Letter width in bits*/
    390 
    391     /*Calculate the col/row start/end on the map*/
    392     int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : (draw_ctx->clip_area->x1 - pos->x) * 3;
    393     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;
    394     int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
    395     int32_t row_end   = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
    396 
    397     /*Move on the map too*/
    398     int32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
    399     map_p += bit_ofs >> 3;
    400 
    401     uint8_t letter_px;
    402     lv_opa_t px_opa;
    403     int32_t col_bit;
    404     col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
    405 
    406     lv_area_t map_area;
    407     map_area.x1 = col_start / 3 + pos->x;
    408     map_area.x2 = col_end / 3  + pos->x - 1;
    409     map_area.y1 = row_start + pos->y;
    410     map_area.y2 = map_area.y1;
    411 
    412     if(map_area.x2 <= map_area.x1) return;
    413 
    414     lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
    415     int32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : g->box_w * g->box_h;
    416     lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
    417     int32_t mask_p = 0;
    418 
    419     lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
    420 
    421     int32_t dest_buf_stride = lv_area_get_width(draw_ctx->buf_area);
    422     lv_color_t * dest_buf_tmp = draw_ctx->buf;
    423 
    424     /*Set a pointer on draw_buf to the first pixel of the letter*/
    425     dest_buf_tmp += ((pos->y - draw_ctx->buf_area->y1) * dest_buf_stride) + pos->x - draw_ctx->buf_area->x1;
    426 
    427     /*If the letter is partially out of mask the move there on draw_buf*/
    428     dest_buf_tmp += (row_start * dest_buf_stride) + col_start / 3;
    429 
    430     lv_area_t mask_area;
    431     lv_area_copy(&mask_area, &map_area);
    432     mask_area.y2 = mask_area.y1 + row_end;
    433     bool mask_any = lv_draw_mask_is_any(&map_area);
    434     uint8_t font_rgb[3];
    435 
    436     lv_color_t color = dsc->color;
    437 #if LV_COLOR_16_SWAP == 0
    438     uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue};
    439 #else
    440     uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue};
    441 #endif
    442 
    443     lv_draw_sw_blend_dsc_t blend_dsc;
    444     lv_memset_00(&blend_dsc, sizeof(blend_dsc));
    445     blend_dsc.blend_area = &map_area;
    446     blend_dsc.mask_area = &map_area;
    447     blend_dsc.src_buf = color_buf;
    448     blend_dsc.mask_buf = mask_buf;
    449     blend_dsc.opa = opa;
    450     blend_dsc.blend_mode = dsc->blend_mode;
    451 
    452     for(row = row_start ; row < row_end; row++) {
    453         uint32_t subpx_cnt = 0;
    454         bitmask = bitmask_init >> col_bit;
    455         int32_t mask_p_start = mask_p;
    456 
    457         for(col = col_start; col < col_end; col++) {
    458             /*Load the pixel's opacity into the mask*/
    459             letter_px = (*map_p & bitmask) >> (8 - col_bit - bpp);
    460             if(letter_px != 0) {
    461                 if(opa >= LV_OPA_MAX) {
    462                     px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px];
    463                 }
    464                 else {
    465                     px_opa = bpp == 8 ? (uint32_t)((uint32_t)letter_px * opa) >> 8
    466                              : (uint32_t)((uint32_t)bpp_opa_table[letter_px] * opa) >> 8;
    467                 }
    468             }
    469             else {
    470                 px_opa = 0;
    471             }
    472 
    473             font_rgb[subpx_cnt] = px_opa;
    474 
    475             subpx_cnt ++;
    476             if(subpx_cnt == 3) {
    477                 subpx_cnt = 0;
    478 
    479                 lv_color_t res_color;
    480 #if LV_COLOR_16_SWAP == 0
    481                 uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red, dest_buf_tmp->ch.green, dest_buf_tmp->ch.blue};
    482 #else
    483                 uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red,
    484                                      (dest_buf_tmp->ch.green_h << 3) + dest_buf_tmp->ch.green_l,
    485                                      dest_buf_tmp->ch.blue
    486                                     };
    487 #endif
    488 
    489 #if LV_FONT_SUBPX_BGR
    490                 res_color.ch.blue = (uint32_t)((uint32_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
    491                 res_color.ch.red = (uint32_t)((uint32_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
    492 #else
    493                 res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
    494                 res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
    495 #endif
    496 
    497 #if LV_COLOR_16_SWAP == 0
    498                 res_color.ch.green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
    499 #else
    500                 uint8_t green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
    501                 res_color.ch.green_h = green >> 3;
    502                 res_color.ch.green_l = green & 0x7;
    503 #endif
    504 
    505 #if LV_COLOR_DEPTH == 32
    506                 res_color.ch.alpha = 0xff;
    507 #endif
    508 
    509                 if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP;
    510                 else mask_buf[mask_p] = LV_OPA_COVER;
    511                 color_buf[mask_p] = res_color;
    512 
    513                 /*Next mask byte*/
    514                 mask_p++;
    515                 dest_buf_tmp++;
    516             }
    517 
    518             /*Go to the next column*/
    519             if(col_bit < (int32_t)(8 - bpp)) {
    520                 col_bit += bpp;
    521                 bitmask = bitmask >> bpp;
    522             }
    523             else {
    524                 col_bit = 0;
    525                 bitmask = bitmask_init;
    526                 map_p++;
    527             }
    528         }
    529 
    530         /*Apply masks if any*/
    531         if(mask_any) {
    532             blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2,
    533                                                     lv_area_get_width(&map_area));
    534             if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
    535                 lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&map_area));
    536             }
    537         }
    538 
    539         if((int32_t) mask_p + (col_end - col_start) < mask_buf_size) {
    540             map_area.y2 ++;
    541         }
    542         else {
    543             lv_draw_sw_blend(draw_ctx, &blend_dsc);
    544 
    545             map_area.y1 = map_area.y2 + 1;
    546             map_area.y2 = map_area.y1;
    547             mask_p = 0;
    548         }
    549 
    550         col_bit += ((box_w - col_end) + col_start) * bpp;
    551 
    552         map_p += (col_bit >> 3);
    553         col_bit = col_bit & 0x7;
    554 
    555         /*Next row in draw_buf*/
    556         dest_buf_tmp += dest_buf_stride - (col_end - col_start) / 3;
    557     }
    558 
    559     /*Flush the last part*/
    560     if(map_area.y1 != map_area.y2) {
    561         map_area.y2--;
    562         lv_draw_sw_blend(draw_ctx, &blend_dsc);
    563     }
    564 
    565     lv_mem_buf_release(mask_buf);
    566     lv_mem_buf_release(color_buf);
    567 }
    568 #endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/
    569