UP LVGL字库加载显示支持

main
JiXieShi 2024-06-25 18:17:14 +08:00
parent dd27c265da
commit 6fb2733bfb
8 changed files with 304 additions and 597 deletions

View File

@ -114,9 +114,12 @@ void Test_OLED() {
int s = 0;
char buf[30] = {0x5B, 0x57, 0x5E, 0x93, 0x75, 0x1F, 0x62, 0x10, 0x6D, 0x4B, 0x8B, 0xD5};
OLED_ShowCHString(&oled, 15, 16, buf);
OLED_Refresh(&oled);
// OLED_ShowCHString(&oled, 15, 16, buf);
extern lv_font_t myFont;
OLED_DisplayString(&oled, &myFont, "你好", 0, 0);
OLED_Refresh(&oled);
_beginthread(Get_Key, 0, NULL);
pageinit();
Sleep(5000);

View File

@ -4,11 +4,11 @@ set(LIBRARIES
HW_LIB_Task src/task inc/task
HW_LIB_Printf src/printf inc/printf
HW_LIB_Utils src/utils inc/utils
HW_LIB_Font src/font inc/font
HW_LIB_Iic src/iic inc/iic
HW_LIB_Spi src/spi inc/spi
HW_LIB_Key src/key inc/key
HW_LIB_Oled src/oled inc/oled
HW_LIB_Font src/font inc/font
)
#
@ -28,4 +28,5 @@ foreach (INDEX RANGE 0 ${LIBRARIES_LENGTH} 3)
endforeach ()
#
target_link_libraries(HW_LIB_Spi HW_LIB_Utils)
target_link_libraries(HW_LIB_Spi HW_LIB_Utils)
target_link_libraries(HW_LIB_Oled HW_LIB_Font)

44
lib/inc/font/font.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#ifndef HW_LIB_FONT_H
#define HW_LIB_FONT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdlib.h"
#include "string.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "lvgl.h"
// 定义像素颜色的位数
#define PIX_COLOR_SIZE 1
// 启用单行刷新
#define LINE_FAST_SHOW
typedef struct Font Font_f_t;
typedef void (*Font_Show_t)(Font_f_t *font, uint8_t *data, size_t len);
struct Font {
void *dev;
uint8_t dev_w;
uint16_t x, y, w, h;
Font_Show_t show;
#if PIX_COLOR_SIZE == 16
uint16_t pixcolor;
uint16_t backgroundcolor;
#endif
};
char Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter);
char Font_draw_letter(const lv_font_t *font, Font_f_t *fd, uint32_t letter, int16_t pos_x, int16_t pos_y);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,20 +0,0 @@
#pragma once
#ifndef __lvgl_font_H
#define __lvgl_font_H
#include "stdlib.h"
#include "string.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "lvgl.h"
#define LV_ANTIALIAS 0 //抗锯齿
char utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter);
char lv_draw_letter(const lv_font_t *font, uint32_t letter, int16_t pos_x, int16_t pos_y);
#endif

View File

@ -6,6 +6,7 @@ extern "C" {
#endif
#include "stdint.h"
#include "lvgl.h"
#define REFRESH_CALL_ENABLE 1 //使用DMA或者整体刷新函数
@ -278,6 +279,9 @@ void OLED_Fill(OLED_T *dev, uint8_t data);
*/
void OLED_CLS(OLED_T *dev);
void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y);
#ifdef __cplusplus
}
#endif

216
lib/src/font/font.cpp Normal file
View File

@ -0,0 +1,216 @@
#include "lvgl.h"
#include "font.h"
char Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter) {
char outputSize = 0;
char ppOutput[8] = {0};
char *tmp = ppOutput; //临时变量,用于遍历输出字符串
if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符英文字母、数字
{
*tmp = *pInput;
tmp++;
*tmp = 0; //小端法表示在高地址填补0
outputSize = 1;
} else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
{
char high = *pInput;
pInput++;
char 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字符
{
char high = *pInput;
pInput++;
char middle = *pInput;
pInput++;
char low = *pInput;
if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
return 0;
*tmp = (middle << 6) + (low & 0x7F);
tmp++;
*tmp = (high << 4) + ((middle >> 2) & 0x0F);
outputSize = 3;
} else //对于其他字节数的UTF8字符不进行处理
{
return 0;
}
unicode_letter[0] = ppOutput[1];
unicode_letter[0] <<= 8;
unicode_letter[0] |= ppOutput[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 / 8];
#endif
int32_t mask_p = 0;
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++) {
int32_t mask_p_start = mask_p;
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++;
}
/*Next mask byte*/
mask_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);
#endif
pos_y++;
mask_p = 0;
} //避免大字体,大缓存 ,单行即刻刷入
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
// LCD_fill_fast(pos_x, pos_y, box_w, box_h, (uint8_t *)mask_buf, box_w * box_h); // 如果 大缓存 一次刷入
}
char 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;
}

View File

@ -1,558 +0,0 @@
#include "lvgl.h"
#include "lvgl_font.h"
#define LV_HOR_RES_MAX 128
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show utf8_to_unicode
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
char utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter) {
char outputSize = 0;
char ppOutput[8] = {0};
char *tmp = ppOutput; //临时变量,用于遍历输出字符串
if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符英文字母、数字
{
*tmp = *pInput;
tmp++;
*tmp = 0; //小端法表示在高地址填补0
outputSize = 1;
} else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
{
char high = *pInput;
pInput++;
char 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字符
{
char high = *pInput;
pInput++;
char middle = *pInput;
pInput++;
char low = *pInput;
if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
return 0;
*tmp = (middle << 6) + (low & 0x7F);
tmp++;
*tmp = (high << 4) + ((middle >> 2) & 0x0F);
outputSize = 3;
} else //对于其他字节数的UTF8字符不进行处理
{
return 0;
}
unicode_letter[0] = ppOutput[1];
unicode_letter[0] <<= 8;
unicode_letter[0] |= ppOutput[0];
return outputSize;
}
void
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show draw_letter_normal
// lv_opa_t opa ; //透明度 0-255
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void draw_letter_normal(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];
uint8_t fbuf[128 / 8];
int32_t mask_p = 0;
uint32_t col_bit_max = 8 - bpp;
uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
uint8_t index = 0;
for (row = row_start; row < row_end; row++) {
int32_t mask_p_start = mask_p;
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 (letter_px) 1;
// else 0;
if (letter_px) {
fbuf[index / 8] |= (1 << (index % 8));
} else {
fbuf[index / 8] &= ~(1 << (index % 8));
}
index++;
/*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++;
}
/*Next mask byte*/
mask_p++;
}
{
// LCD_fill_fast(pos_x, pos_y, box_w, 1, (uint8_t *)mask_buf, box_w);
//// 读取fbuf的当前位置的二进制位
//bool read_bit = (fbuf[pos / 8] >> (pos % 8)) & 1;
pos_y++;
mask_p = 0;
} //避免大字体,大缓存 ,单行即刻刷入
col_bit += col_bit_row_ofs;
map_p += (col_bit >> 3);
col_bit = col_bit & 0x7;
}
// LCD_fill_fast(pos_x, pos_y, box_w, box_h, (uint8_t *)mask_buf, box_w * box_h); // 如果 大缓存 一次刷入
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show lv_draw_letter
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
char lv_draw_letter(const lv_font_t *font, 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(pos_x, pos_y, &g, map_p);
return g.box_w;
}
#if LV_FONT_UNSCII_8
/** Searches base[0] to base[n - 1] for an item that matches *key.
*
* @note The function cmp must return negative if its first
* argument (the search key) is less that its second (a table entry),
* zero if equal, and positive if greater.
*
* @note Items in the array must be in ascending order.
*
* @param key Pointer to item being searched for
* @param base Pointer to first element to search
* @param n Number of elements
* @param size Size of each element
* @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function
* example)
*
* @return a pointer to a matching item, or NULL if none exists.
*/
void *_lv_utils_bsearch(const void *key, const void *base, uint32_t n, uint32_t size,
int32_t (*cmp)(const void *pRef, const void *pElement))
{
const char *middle;
int32_t c;
for (middle = base; n != 0;)
{
middle += (n / 2) * size;
if ((c = (*cmp)(key, middle)) > 0)
{
n = (n / 2) - ((n & 1) == 0);
base = (middle += size);
}
else if (c < 0)
{
n /= 2;
middle = base;
}
else
{
return (char *)middle;
}
}
return NULL;
}
/** Code Comparator.
*
* Compares the value of both input arguments.
*
* @param[in] pRef Pointer to the reference.
* @param[in] pElement Pointer to the element to compare.
*
* @return Result of comparison.
* @retval < 0 Reference is greater than element.
* @retval = 0 Reference is equal to element.
* @retval > 0 Reference is less than element.
*
*/
static int32_t unicode_list_compare(const void *ref, const void *element)
{
return ((int32_t)(*(uint16_t *)ref)) - ((int32_t)(*(uint16_t *)element));
}
/**********************
* STATIC FUNCTIONS
**********************/
static uint32_t get_glyph_dsc_id(const lv_font_t *font, uint32_t letter)
{
if (letter == '\0')
return 0;
lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
/*Check the cache first*/
if (letter == fdsc->last_letter)
return fdsc->last_glyph_id;
uint16_t i;
for (i = 0; i < fdsc->cmap_num; i++)
{
/*Relative code point*/
uint32_t rcp = letter - fdsc->cmaps[i].range_start;
if (rcp > fdsc->cmaps[i].range_length)
continue;
uint32_t glyph_id = 0;
if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY)
{
glyph_id = fdsc->cmaps[i].glyph_id_start + rcp;
}
else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL)
{
const uint8_t *gid_ofs_8 = fdsc->cmaps[i].glyph_id_ofs_list;
glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp];
}
else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY)
{
uint16_t key = rcp;
uint8_t *p = _lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length,
sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare);
if (p)
{
lv_uintptr_t ofs = (lv_uintptr_t)(p - (uint8_t *)fdsc->cmaps[i].unicode_list);
ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/
glyph_id = fdsc->cmaps[i].glyph_id_start + ofs;
}
}
else if (fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL)
{
uint16_t key = rcp;
uint8_t *p = _lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length,
sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare);
if (p)
{
lv_uintptr_t ofs = (lv_uintptr_t)(p - (uint8_t *)fdsc->cmaps[i].unicode_list);
ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/
const uint8_t *gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list;
glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_16[ofs];
}
}
/*Update the cache*/
fdsc->last_letter = letter;
fdsc->last_glyph_id = glyph_id;
return glyph_id;
}
fdsc->last_letter = letter;
fdsc->last_glyph_id = 0;
return 0;
}
/**
* Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed.
* @param font pointer to font
* @param unicode_letter an unicode letter which bitmap should be get
* @return pointer to the bitmap or NULL if not found
*/
const uint8_t *lv_font_get_bitmap_fmt_txt(const lv_font_t *font, uint32_t unicode_letter)
{
if (unicode_letter == '\t')
unicode_letter = ' ';
lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
uint32_t gid = get_glyph_dsc_id(font, unicode_letter);
if (!gid)
return NULL;
const lv_font_fmt_txt_glyph_dsc_t *gdsc = &fdsc->glyph_dsc[gid];
if (fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN)
{
if (gdsc)
return &fdsc->glyph_bitmap[gdsc->bitmap_index];
}
/*Handle compressed bitmap*/
else
{
#if LV_USE_FONT_COMPRESSED
uint32_t gsize = gdsc->box_w * gdsc->box_h;
if (gsize == 0)
return NULL;
uint32_t buf_size = gsize;
/*Compute memory size needed to hold decompressed glyph, rounding up*/
switch (fdsc->bpp)
{
case 1:
buf_size = (gsize + 7) >> 3;
break;
case 2:
buf_size = (gsize + 3) >> 2;
break;
case 3:
buf_size = (gsize + 1) >> 1;
break;
case 4:
buf_size = (gsize + 1) >> 1;
break;
}
if (_lv_mem_get_size(LV_GC_ROOT(_lv_font_decompr_buf)) < buf_size)
{
LV_GC_ROOT(_lv_font_decompr_buf) = lv_mem_realloc(LV_GC_ROOT(_lv_font_decompr_buf), buf_size);
LV_ASSERT_MEM(LV_GC_ROOT(_lv_font_decompr_buf));
if (LV_GC_ROOT(_lv_font_decompr_buf) == NULL)
return NULL;
}
bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED ? true : false;
decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], LV_GC_ROOT(_lv_font_decompr_buf), gdsc->box_w, gdsc->box_h,
(uint8_t)fdsc->bpp,
prefilter);
return LV_GC_ROOT(_lv_font_decompr_buf);
#else /* !LV_USE_FONT_COMPRESSED */
return NULL;
#endif
}
/*If not returned earlier then the letter is not found in this font*/
return NULL;
}
static int32_t kern_pair_8_compare(const void *ref, const void *element)
{
const uint8_t *ref8_p = ref;
const uint8_t *element8_p = element;
/*If the MSB is different it will matter. If not return the diff. of the LSB*/
if (ref8_p[0] != element8_p[0])
return (int32_t)ref8_p[0] - element8_p[0];
else
return (int32_t)ref8_p[1] - element8_p[1];
}
static int32_t kern_pair_16_compare(const void *ref, const void *element)
{
const uint16_t *ref16_p = ref;
const uint16_t *element16_p = element;
/*If the MSB is different it will matter. If not return the diff. of the LSB*/
if (ref16_p[0] != element16_p[0])
return (int32_t)ref16_p[0] - element16_p[0];
else
return (int32_t)ref16_p[1] - element16_p[1];
}
static int8_t get_kern_value(const lv_font_t *font, uint32_t gid_left, uint32_t gid_right)
{
lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
int8_t value = 0;
if (fdsc->kern_classes == 0)
{
/*Kern pairs*/
const lv_font_fmt_txt_kern_pair_t *kdsc = fdsc->kern_dsc;
if (kdsc->glyph_ids_size == 0)
{
/* Use binary search to find the kern value.
* The pairs are ordered left_id first, then right_id secondly. */
const uint8_t *g_ids = kdsc->glyph_ids;
uint16_t g_id_both = (gid_right << 8) + gid_left; /*Create one number from the ids*/
uint8_t *kid_p = _lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 2, kern_pair_8_compare);
/*If the `g_id_both` were found get its index from the pointer*/
if (kid_p)
{
lv_uintptr_t ofs = (lv_uintptr_t)(kid_p - g_ids);
ofs = ofs >> 1; /*ofs is for pair, divide by 2 to refer as a single value*/
value = kdsc->values[ofs];
}
}
else if (kdsc->glyph_ids_size == 1)
{
/* Use binary search to find the kern value.
* The pairs are ordered left_id first, then right_id secondly. */
const uint16_t *g_ids = kdsc->glyph_ids;
lv_uintptr_t g_id_both = (uint32_t)((uint32_t)gid_right << 8) + gid_left; /*Create one number from the ids*/
uint8_t *kid_p = _lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 4, kern_pair_16_compare);
/*If the `g_id_both` were found get its index from the pointer*/
if (kid_p)
{
lv_uintptr_t ofs = (lv_uintptr_t)(kid_p - (const uint8_t *)g_ids);
ofs = ofs >> 4; /*ofs is 4 byte pairs, divide by 4 to refer as a single value*/
value = kdsc->values[ofs];
}
}
else
{
/*Invalid value*/
}
}
else
{
/*Kern classes*/
const lv_font_fmt_txt_kern_classes_t *kdsc = fdsc->kern_dsc;
uint8_t left_class = kdsc->left_class_mapping[gid_left];
uint8_t right_class = kdsc->right_class_mapping[gid_right];
/* If class = 0, kerning not exist for that glyph
* else got the value form `class_pair_values` 2D array*/
if (left_class > 0 && right_class > 0)
{
value = kdsc->class_pair_values[(left_class - 1) * kdsc->right_class_cnt + (right_class - 1)];
}
}
return value;
}
/**
* Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed.
* @param font_p pointer to font
* @param dsc_out store the result descriptor here
* @param letter an UNICODE letter code
* @return true: descriptor is successfully loaded into `dsc_out`.
* false: the letter was not found, no data is loaded to `dsc_out`
*/
bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t *font, lv_font_glyph_dsc_t *dsc_out, uint32_t unicode_letter,
uint32_t unicode_letter_next)
{
bool is_tab = false;
if (unicode_letter == '\t')
{
unicode_letter = ' ';
is_tab = true;
}
lv_font_fmt_txt_dsc_t *fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
uint32_t gid = get_glyph_dsc_id(font, unicode_letter);
if (!gid)
return false;
int8_t kvalue = 0;
if (fdsc->kern_dsc)
{
uint32_t gid_next = get_glyph_dsc_id(font, unicode_letter_next);
if (gid_next)
{
kvalue = get_kern_value(font, gid, gid_next);
}
}
/*Put together a glyph dsc*/
const lv_font_fmt_txt_glyph_dsc_t *gdsc = &fdsc->glyph_dsc[gid];
int32_t kv = ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
uint32_t adv_w = gdsc->adv_w;
if (is_tab)
adv_w *= 2;
adv_w += kv;
adv_w = (adv_w + (1 << 3)) >> 4;
dsc_out->adv_w = adv_w;
dsc_out->box_h = gdsc->box_h;
dsc_out->box_w = gdsc->box_w;
dsc_out->ofs_x = gdsc->ofs_x;
dsc_out->ofs_y = gdsc->ofs_y;
dsc_out->bpp = (uint8_t)fdsc->bpp;
if (is_tab)
dsc_out->box_w = dsc_out->box_w * 2;
return true;
}
#endif

View File

@ -1,7 +1,7 @@
#include "oled.h"
#include "oled_font.h"
#include "oled_font_chuc.h"
#include "../../inc/font/lvgl_font.h"
#include "font.h"
#define BUFPOINT(x, y) (*(dev->buf + x + (y * dev->width)))
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
@ -248,21 +248,38 @@ void OLED_ShowCHString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *str) {
}
}
}
void draw_rect(Font_f_t *fd, uint8_t *data, size_t len) {
size_t index;
uint16_t x = fd->x, y = fd->y;
uint8_t bit;
for (index = 0; index < len; index++) {
bit = (data[index / 8] >> (index % 8)) & 1;
if (bit)OLED_Set((OLED_T *) fd->dev, x, y);
else OLED_RSet((OLED_T *) fd->dev, x, y);
x++;
if ((x - fd->x) == fd->w) {
y++;
x = fd->x;
}
}
}
//
//void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y) {
// uint32_t unicode_letter;
// while (*s) {
// if (font) {
// s += utf8_to_unicode(s, &unicode_letter);
// x += lv_draw_letter(font, unicode_letter, x, y);
// x += 2; //字间距
// } else {
// OLED_ShowChar(dev, x, y, *s, 6);
// x += 6;
// s++;
// }
// }
//}
void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y) {
uint32_t unicode_letter;
Font_f_t fd = {.dev=dev, .dev_w=dev->width, .show=draw_rect};
while (*s) {
if (font) {
s += Font_utf8_to_unicode(s, &unicode_letter);
x += Font_draw_letter(font, &fd, unicode_letter, x, y);
x += 2; //字间距
} else {
OLED_ShowChar(dev, x, y, *s, 12);
x += 6;
s++;
}
}
}
uint32_t OLED_Pow(uint8_t m, uint8_t n) {
uint32_t result = 1;