#include "lvgl_font.h"
#include "font_t.h"

uint8_t Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter) {
    uint8_t outputSize = 0;
    uint8_t * tmp= ( uint8_t *) unicode_letter;
    if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字)
    {
        *tmp = *pInput;
        tmp++;
        *tmp = 0; //小端法表示,在高地址填补0
        outputSize = 1;
    } else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
    {
        uint8_t high = *pInput;
        pInput++;
        uint8_t low = *pInput;

        if ((low & 0xC0) != 0x80) //检查是否为合法的UTF8字符表示
            return 0;             //如果不是则报错
        *tmp = (high << 6) + (low & 0x3F);
        tmp++;
        *tmp = (high >> 2) & 0x07;
        outputSize = 2;
    } else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符
    {
        uint8_t high = *pInput;
        pInput++;
        uint8_t middle = *pInput;
        pInput++;
        uint8_t low = *pInput;
        if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
            return 0;
        *tmp = (middle << 6) | (low & 0x3F);
        tmp++;
        *tmp = (high << 4) | ((middle >> 2) & 0x0F);
        outputSize = 3;
    } else //对于其他字节数的UTF8字符不进行处理
    {
        return 0;
    }
    return outputSize;
}

void draw_letter_normal(Font_f_t *fd, uint16_t pos_x, uint16_t pos_y, lv_font_glyph_dsc_t *g, const uint8_t *map_p) {
    uint32_t bitmask_init;
    uint32_t bitmask;
    uint32_t bpp = g->bpp;

    if (bpp == 3)
        bpp = 4;

    switch (bpp) {
        case 1:
            bitmask_init = 0x80;
            break;
        case 2:
            bitmask_init = 0xC0;
            break;
        case 4:
            bitmask_init = 0xF0;
            break;
        case 8:
            bitmask_init = 0xFF;
            break;
        default:
            return; /*Invalid bpp. Can't render the letter*/
    }

    int32_t col, row;
    int32_t box_w = g->box_w;
    int32_t box_h = g->box_h;
    int32_t width_bit = box_w * bpp; /*Letter width in bits*/

    /* Calculate the col/row start/end on the map*/
    int32_t col_start = 0;
    int32_t col_end = box_w;
    int32_t row_start = 0;
    int32_t row_end = box_h;

    /*Move on the map too*/
    uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
    map_p += bit_ofs >> 3;

    uint8_t letter_px;
    uint32_t col_bit;
    col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */

    // uint32_t mask_buf_size = box_w * box_h > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : box_w * box_h;
//    unsigned short mask_buf[LV_HOR_RES_MAX / 2];
#if PIX_COLOR_SIZE == 1
    uint8_t fd_buf[fd->dev_w / 2];
#endif
#if PIX_COLOR_SIZE == 16
    uint16_t fd_buf[fd->dev_w / 2];
#endif
    uint32_t col_bit_max = 8 - bpp;
    uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
    uint16_t index = 0;
    for (row = row_start; row < row_end; row++) {
        bitmask = bitmask_init >> col_bit;
        for (col = col_start; col < col_end; col++) {
            /*Load the pixel's opacity into the mask*/
            letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);

#if PIX_COLOR_SIZE == 1
            if (letter_px) {
                fd_buf[index / 8] |= (1 << (index % 8));
            } else {
                fd_buf[index / 8] &= ~(1 << (index % 8));
            }
            index++;
#endif

#if PIX_COLOR_SIZE == 16
            if (letter_px) {
                fd_buf[index] = fd->pixcolor;
            } else {
                fd_buf[index] = fd->backgroundcolor;
            }
            index++;
#endif
            /*Go to the next column*/
            if (col_bit < col_bit_max) {
                col_bit += bpp;
                bitmask >>= bpp;
            } else {
                col_bit = 0;
                bitmask = bitmask_init;
                map_p++;
            }
        }

        {

            //            LCD_fill_fast(pos_x, pos_y, box_w, 1, (uint8_t *)mask_buf, box_w);
#ifdef LINE_FAST_SHOW
            fd->x = pos_x;
            fd->y = pos_y;
            fd->w = box_w;
            fd->h = 1;
            fd->show(fd, fd_buf, box_w);
            pos_y++;
            index = 0;
#endif


        } //避免大字体,大缓存 ,单行即刻刷入

        col_bit += col_bit_row_ofs;
        map_p += (col_bit >> 3);
        col_bit = col_bit & 0x7;
    }
#ifndef LINE_FAST_SHOW
    fd->x = pos_x;
    fd->y = pos_y;
    fd->w = box_w;
    fd->h = box_h;
    fd->show(fd, fd_buf, box_w * box_h);
#endif
}

uint8_t Font_draw_letter(const lv_font_t *font, Font_f_t *fd, uint32_t letter, int16_t pos_x, int16_t pos_y) {
    const uint8_t *map_p;

    lv_font_glyph_dsc_t g;
    if (!font->get_glyph_dsc(font, &g, letter, '\0')) //获取字体 信息
        return 0;

    if (letter == ' ') // lvgl 空格没有实际数据 直接跳过
        return g.box_w;

    /* Don't draw anything if the character is empty. E.g. space */
    if ((g.box_h == 0) || (g.box_w == 0))
        return 0;

    map_p = font->get_glyph_bitmap(font, letter); //获取字体 实际数据
    if (map_p == NULL)
        return 0;

    pos_x += g.ofs_x; //偏移修正
    pos_y += font->line_height - g.box_h - g.ofs_y;

    if (pos_x < 1) //有的时候会为负
        pos_x = 1;
    if (pos_y < 1) //有的时候会为负
        pos_y = 1;

    draw_letter_normal(fd, pos_x, pos_y, &g, map_p);

    return g.box_w;
}