UP 路径优化
This commit is contained in:
193
lib/font/font.cpp
Normal file
193
lib/font/font.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
|
||||
#include "lvgl_font.h"
|
||||
#include "font.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;
|
||||
}
|
44
lib/font/inc/font.h
Normal file
44
lib/font/inc/font.h
Normal 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_font.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
|
||||
};
|
||||
|
||||
uint8_t Font_utf8_to_unicode(uint8_t *pInput, uint32_t *unicode_letter);
|
||||
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
224
lib/font/inc/lvgl_font.h
Normal file
224
lib/font/inc/lvgl_font.h
Normal file
@@ -0,0 +1,224 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __lvgl_H
|
||||
#define __lvgl_H
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Attribute to mark large constant arrays for example
|
||||
* font's bitmaps */
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/** Format of font character map. */
|
||||
enum {
|
||||
LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY,
|
||||
LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL,
|
||||
LV_FONT_FMT_TXT_CMAP_SPARSE_TINY,
|
||||
LV_FONT_FMT_TXT_CMAP_SPARSE_FULL,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_font_fmt_txt_cmap_type_t;
|
||||
|
||||
typedef uint8_t lv_opa_t;
|
||||
|
||||
/** This describes a glyph. */
|
||||
typedef struct {
|
||||
#if LV_FONT_FMT_TXT_LARGE == 0
|
||||
uint32_t bitmap_index: 20; /**< Start index of the bitmap. A font can be max 1 MB. */
|
||||
uint32_t adv_w: 12; /**< Draw the next glyph after this width. 8.4 format (real_value * 16 is stored). */
|
||||
uint8_t box_w; /**< Width of the glyph's bounding box*/
|
||||
uint8_t box_h; /**< Height of the glyph's bounding box*/
|
||||
int8_t ofs_x; /**< x offset of the bounding box*/
|
||||
int8_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
|
||||
#else
|
||||
uint32_t bitmap_index; /**< Start index of the bitmap. A font can be max 4 GB. */
|
||||
uint32_t adv_w; /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored). */
|
||||
uint16_t box_w; /**< Width of the glyph's bounding box*/
|
||||
uint16_t box_h; /**< Height of the glyph's bounding box*/
|
||||
int16_t ofs_x; /**< x offset of the bounding box*/
|
||||
int16_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
|
||||
#endif
|
||||
} lv_font_fmt_txt_glyph_dsc_t;
|
||||
|
||||
/* 将码点映射到 `glyph_dsc` 的结构体
|
||||
* 支持多种格式以优化内存使用
|
||||
* 详见 https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md
|
||||
*/
|
||||
typedef struct {
|
||||
/** 此范围的第一个Unicode字符 */
|
||||
uint32_t range_start;
|
||||
|
||||
/** 与此范围相关的Unicode字符数。
|
||||
* 最后一个Unicode字符 = range_start + range_length - 1*/
|
||||
uint16_t range_length;
|
||||
|
||||
/** 此范围的第一个字形ID(`glyph_dsc` 的数组索引) */
|
||||
uint16_t glyph_id_start;
|
||||
|
||||
/*
|
||||
根据规范,有4种格式:
|
||||
https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md
|
||||
|
||||
为简单起见引入“相对码点”:
|
||||
rcp = codepoint - range_start
|
||||
|
||||
和一个搜索函数:
|
||||
在“数组”中搜索“值”并返回“值”的索引。
|
||||
|
||||
格式0 紧凑
|
||||
unicode_list == NULL && glyph_id_ofs_list == NULL
|
||||
glyph_id = glyph_id_start + rcp
|
||||
|
||||
格式0 完整
|
||||
unicode_list == NULL && glyph_id_ofs_list != NULL
|
||||
glyph_id = glyph_id_start + glyph_id_ofs_list[rcp]
|
||||
|
||||
Fomat 紧凑
|
||||
unicode_list != NULL && glyph_id_ofs_list == NULL
|
||||
glyph_id = glyph_id_start + search(unicode_list, rcp)
|
||||
|
||||
Fomat 完整
|
||||
unicode_list != NULL && glyph_id_ofs_list != NULL
|
||||
glyph_id = glyph_id_start + glyph_id_ofs_list[search(unicode_list, rcp)]
|
||||
*/
|
||||
|
||||
const uint16_t *unicode_list;
|
||||
|
||||
/** 如果(type == LV_FONT_FMT_TXT_CMAP_FORMAT0_...),则为 `uint8_t *`
|
||||
* 如果(type == LV_FONT_FMT_TXT_CMAP_SPARSE_...),则为 `uint16_t *`
|
||||
*/
|
||||
const void *glyph_id_ofs_list;
|
||||
|
||||
/** `unicode_list` 和/或 `glyph_id_ofs_list` 的长度 */
|
||||
uint16_t list_length;
|
||||
|
||||
/** 此字符映射的类型 */
|
||||
lv_font_fmt_txt_cmap_type_t type;
|
||||
} lv_font_fmt_txt_cmap_t;
|
||||
|
||||
/* 描述字体的附加数据的结构体 */
|
||||
typedef struct {
|
||||
/* 所有字形的位图 */
|
||||
const uint8_t *glyph_bitmap;
|
||||
|
||||
/* 描述字形 */
|
||||
const lv_font_fmt_txt_glyph_dsc_t *glyph_dsc;
|
||||
|
||||
/* 将字形映射到Unicode字符。
|
||||
* `lv_font_cmap_fmt_txt_t` 变量的数组 */
|
||||
const lv_font_fmt_txt_cmap_t *cmaps;
|
||||
|
||||
/* 存储字距值。
|
||||
* 可以是 `lv_font_fmt_txt_kern_pair_t *` 或 `lv_font_kern_classes_fmt_txt_t *`
|
||||
* 取决于 `kern_classes` */
|
||||
const void *kern_dsc;
|
||||
|
||||
/* 缩放字距值,12.4格式 */
|
||||
uint16_t kern_scale;
|
||||
|
||||
/* cmap表的数量 */
|
||||
uint16_t cmap_num: 10;
|
||||
|
||||
/* 每像素位数:1, 2, 3, 4, 8 */
|
||||
uint16_t bpp: 4;
|
||||
|
||||
/* `kern_dsc` 的类型 */
|
||||
uint16_t kern_classes: 1;
|
||||
|
||||
/*
|
||||
* 位图的存储格式
|
||||
* 取自 `lv_font_fmt_txt_bitmap_format_t`
|
||||
*/
|
||||
uint16_t bitmap_format: 2;
|
||||
|
||||
/* 缓存最后一个字母和其字形ID */
|
||||
uint32_t last_letter;
|
||||
uint32_t last_glyph_id;
|
||||
|
||||
} lv_font_fmt_txt_dsc_t;
|
||||
|
||||
/* 坐标类型。应为 `int16_t`(或在极端情况下为 `int32_t`) */
|
||||
typedef int16_t lv_coord_t;
|
||||
|
||||
/** 描述字形属性的结构体 */
|
||||
typedef struct {
|
||||
uint16_t adv_w; /**< 字形所需的空间。在此宽度后绘制下一个字形。8位整数,4位小数 */
|
||||
uint16_t box_w; /**< 字形的包围框宽度 */
|
||||
uint16_t box_h; /**< 字形的包围框高度 */
|
||||
int16_t ofs_x; /**< 包围框的x偏移量 */
|
||||
int16_t ofs_y; /**< 包围框的y偏移量 */
|
||||
uint8_t bpp; /**< 每像素位数:1, 2, 4, 8 */
|
||||
} lv_font_glyph_dsc_t;
|
||||
|
||||
/** 描述字体的属性的结构体 */
|
||||
typedef struct _lv_font_struct {
|
||||
/** 从字体中获取字形描述符 */
|
||||
bool (*get_glyph_dsc)(const struct _lv_font_struct *, lv_font_glyph_dsc_t *, uint32_t letter, uint32_t letter_next);
|
||||
|
||||
/** 从字体中获取字形的位图 */
|
||||
const uint8_t *(*get_glyph_bitmap)(const struct _lv_font_struct *, uint32_t);
|
||||
|
||||
/* 指向字体包中的字体的指针(必须具有相同的行高) */
|
||||
lv_coord_t line_height; /**< 任何文本都适合的实际行高 */
|
||||
lv_coord_t base_line; /**< 从行高顶部测量的基准线 */
|
||||
uint8_t subpx: 2; /**< `lv_font_subpx_t` 的一个元素 */
|
||||
|
||||
int8_t underline_position; /**< 下划线顶部与基准线之间的距离(< 0 表示在基准线下方)*/
|
||||
int8_t underline_thickness; /**< 下划线的厚度 */
|
||||
|
||||
void *dsc; /**< 在这里存储特定于实现或运行时数据或缓存 */
|
||||
} lv_font_t;
|
||||
|
||||
|
||||
//#define NULL 0 /* see <stddef.h> */
|
||||
|
||||
/** Bitmap formats*/
|
||||
typedef enum {
|
||||
LV_FONT_FMT_TXT_PLAIN = 0,
|
||||
LV_FONT_FMT_TXT_COMPRESSED = 1,
|
||||
LV_FONT_FMT_TXT_COMPRESSED_NO_PREFILTER = 1,
|
||||
} lv_font_fmt_txt_bitmap_format_t;
|
||||
|
||||
|
||||
typedef uintptr_t lv_uintptr_t;
|
||||
|
||||
|
||||
/** 用于简单映射字距值对的结构体 */
|
||||
typedef struct {
|
||||
/* 获取两个字符代码点之间的字距值:
|
||||
1. 从 `lv_font_fmt_txt_cmap_t` 中获取 `glyph_id_left` 和 `glyph_id_right`
|
||||
2. for(i = 0; i < pair_cnt * 2; i+2)
|
||||
if(gylph_ids[i] == glyph_id_left &&
|
||||
gylph_ids[i+1] == glyph_id_right)
|
||||
return values[i / 2];
|
||||
*/
|
||||
const void *glyph_ids; /* 存储字形ID对 */
|
||||
const int8_t *values; /* 存储字距值 */
|
||||
uint32_t pair_cnt: 24; /* 字距值对的数量 */
|
||||
uint32_t glyph_ids_size: 2; /* 0: `glyph_ids` 存储为 `uint8_t`; 1: 存储为 `uint16_t` */
|
||||
} lv_font_fmt_txt_kern_pair_t;
|
||||
|
||||
/** 更复杂但更优化的基于类别的字距值存储结构体 */
|
||||
typedef struct {
|
||||
/* 结构体用于获取两个字符代码点之间的字距值:
|
||||
1. 从 `lv_font_fmt_txt_cmap_t` 中获取 `glyph_id_left` 和 `glyph_id_right`
|
||||
2. 获取左侧和右侧字形的类别,分别为 `left_class` 和 `right_class`
|
||||
left_class = left_class_mapping[glyph_id_left];
|
||||
right_class = right_class_mapping[glyph_id_right];
|
||||
3. value = class_pair_values[(left_class-1)*right_class_cnt + (right_class-1)]
|
||||
*/
|
||||
|
||||
const int8_t *class_pair_values; /* 存储左侧类别数 * 右侧类别数的值 */
|
||||
const uint8_t *left_class_mapping; /* 将字形ID映射到类别:索引 -> 字形ID -> 类别ID */
|
||||
const uint8_t *right_class_mapping; /* 将字形ID映射到类别:索引 -> 字形ID -> 类别ID */
|
||||
uint8_t left_class_cnt; /* 左侧类别数 */
|
||||
uint8_t right_class_cnt; /* 右侧类别数 */
|
||||
} lv_font_fmt_txt_kern_classes_t;
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user