194 lines
5.4 KiB
C++
194 lines
5.4 KiB
C++
|
||
#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;
|
||
}
|