UP LVGL字库加载显示支持
parent
dd27c265da
commit
6fb2733bfb
|
@ -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);
|
||||
|
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue