杰理字库接入
📎 原始文档:https://www.kdocs.cn/l/cgEzXCKFyroC 杰理字库接入
一、编写目的
本文档目的在于协助用户在使用第三方ui框架的情况下接入杰理字库,目前杰理字库支持多种语言,包括但不限于阿拉伯语、印地语和希伯来语等,下文将会从必要文件、字库使用流程以及简单的显示实验来进行讲解,用户可以基于显示实验的代码进行二次封装。
二、必要文件
- ui_core.h(提供结构体ui_text_attrs定义)
- ui_new.a(底层字库属性相关实现)
- fontinit.c(字库配置文件)
- ui_platform.c(提供字模buf回调函数定义)
- language_list.h(语言id表,不能修改id顺序)
- font_new.a(提供底层字库实现)
- imb_demo.c(参考样例,用户可以基于此部分代码自行修改)
- .PIX、.TAB文件(字模文件)
- font_all.h(提供结构体font_info定义以及相关标志位)
- lib_system_config.c(unicode字库开关)
以上文件除下文提到的imb_demo.c以外,其他文件均跟随sdk发布,均可在sdk中找到
修改为unicode字库请参考:《多国语言及字库指南》第三章第五点
生成字模文件请参考:《字模提取工具说明》
三、字库使用流程
- ascii字库显示
必要工具函数:
/**
* @brief 该函数的作用是将图像压缩成L1格式(定义在ui_platform.c)
*
* @param pix 原始输入图像buf
* @param pix_buf 转换后的图像buf
* @param stride 转换后图像跨度
* @param x 起始像素x
* @param y 起始像素y
* @param height 高度
* @param width 宽度
*/
void l1_data_transformation(u8 *pix, u8 *pix_buf, u32 stride, int x, int y, int height, int width)
{
int i, j, k = -1, h;
for (j = 0; j < (height + 7) / 8; j++) { /* 纵向8像素为1字节 */
for (i = 0; i < width; i++) {
if ((i % 8) == 0) {
k++;
}
u8 pixel = pix[j * width + i];
int hh = height - (j * 8);
if (hh > 8) {
hh = 8;
}
for (h = 0; h < hh; h++) {
u16 clr = pixel & BIT(h) ? 1 : 0;
if (clr) {
pix_buf[(j * 8 + h) * stride + k] |= (1 << (7 - (i % 8)));
}
} /* endof for h */
}/* endof for i */
k = -1;
}/* endof for j */
}
//ascii字模拼接
/**
* @brief 该函数的作用是根据输入字符串,在ascii字库中找到相应字模信息以及数据,
* 并将字模数据转换为L1格式(定义在imb_demo.c)
*
* @param str 输入字符串
* @param str_width 输出字符串宽度
* @param str_height 输出字符串高度
* @return u8*
*/
u8 *ascii_image_splice(char *str, int *str_width, int *str_height)
{
int width;
int height;
int realsize_w;
int realsize_h;
u8 pixel[128];
char *p;
int offset = 0;
u8 *pixbuf = NULL;
u8 *pixbuf_temp;
realsize_w = 0;
realsize_h = 0;
p = str;
while (*p) {//计算ascii的总长度
font_ascii_get_pix(*p, pixel, sizeof(pixel), &height, &width);
realsize_w += width;
p++;
}
realsize_h = height;
u16 stride = (realsize_w + 31) / 32 * 32 / 8;
pixbuf = br28_zalloc(stride * realsize_h);
if (!pixbuf) {
return 0;
}
pixbuf_temp = br28_zalloc((realsize_w + 7) / 8 * realsize_h);
if (!pixbuf_temp) {
return 0;
}
p = str;
while (*p) {//获取ascii字模
int i;
/*
字库字模排列
L ... L
. ... .
. ... .
. ... .
M ... M
L ... L
. ... .
. ... .
. ... .
M ... M
*/
font_ascii_get_pix(*p, pixel, sizeof(pixel), &height, &width);
for (i = 0; i < height / 8; i++) {
memcpy(pixbuf_temp + realsize_w * i + offset, pixel + width * i, width);
}
offset += width;
p++;
}
/*
L1图像排列
M ... L M ... L
. ... . . ... .
. ... . . ... .
. ... . . ... .
M ... L M ... L
*/
l1_data_transformation(pixbuf_temp, pixbuf, stride, 0, 0, realsize_h, realsize_w);//ascii字模转换成L1格式的图像
if (pixbuf_temp) {
br28_free(pixbuf_temp);
}
*str_width = realsize_w;
*str_height = realsize_h;
return pixbuf;
}
主要显示代码:
//字库显示测试(为了提高效率,建议先将字库拼接成一张单色的图像)
int width;
int height;
//打开ascii.res文件
ret = font_ascii_init(RES_PATH"font/ascii.res");
ASSERT(!ret);
//获取“0123a456789”的字模数据,并存放在pixbuf
//以及获取字符串宽高,分别存放在width,height
u8 *pixbuf = ascii_image_splice("0123a456789", &width, &height);
ASSERT(pixbuf);
//创建字符串显示任务,放置在坐标为(120, 120)处,字符串颜色为红色
imb_create_text_task(120, 120, width, height, pixbuf, 0xf800);
- 中文字库显示
imb字库显示任务创建:
/*----------------------------------------------------------------------------*/
/**@brief 创建字库文字显示任务
@param x:相对背景的x坐标
@param y:相对背景的y坐标
@param width:显示的宽度
@param height:显示的高度
@param pixbuf:内存图片的起始地址
@param color:文字的颜色(RGB565格式)
@return
@note 从效率角度考虑,建议先把字库的文字拼接成图片,再创建任务从sram加载显示
*/
/*----------------------------------------------------------------------------*/
void imb_create_text_task(int x, int y, int width, int height, u8 *pixbuf, u16 color)
{
struct imb_task_info imb_tsk_info = {0};
struct imb_task *p = NULL;
imb_tsk_info.data_src = DATA_SRC_SRAM;
imb_tsk_info.cur_in_flash = 0;
imb_tsk_info.zip_en = 0;
imb_tsk_info.in_format = LAYER_FORMAT_L1;
imb_tsk_info.x_offset = x;
imb_tsk_info.y_offset = y;
imb_tsk_info.src_w = (width + 31) / 32 * 32;//设置32对齐
imb_tsk_info.src_h = height;
imb_tsk_info.des_w = (width + 31) / 32 * 32;//设置32对齐
imb_tsk_info.des_h = height;
imb_tsk_info.text_color = color;
imb_tsk_info.priv = pixbuf;
imb_tsk_info.ui_malloc = 1;
imb_tsk_info.elm_id = elm_id++;
/* elm_id、id可作为任务的唯一标识,通过该标识搜索任务句柄,若搜到则重置任务信息,没搜到则创建任务 */
/* p = imb_task_search_by_id(imb_task_head_get(0), imb_tsk_info.elm_id, imb_tsk_info.id); */
if (p) {
imb_task_reset(imb_task_head_get(0), p, &imb_tsk_info);
} else {
imb_task_list_add(imb_task_head_get(0), &imb_tsk_info);
}
}
utf8显示实验代码:
//字模buffer
u8 *pixbuf1 = NULL;
//必要函数声明:
void font_get_text_width(u8 encode, struct font_info *info, u8 *str, u16 strlen);//获取字符串宽度
struct font_info *text_font_init(u8 init);//字库初始化
///待显示字符串(必须为静态)
static char *text_t = "你好abc";
//设置为中文简体id
font_lang_set(Chinese_Simplified);
//根据fontinit.c里面的struct font_info font_info_table
//对相应的语言进行初始化,配置.PIX、.TAB等字模文件以及回调函数
struct font_info *f_info = text_font_init(true);
//标志位设置,可以通过或上FONT_SHOW_MULTI_LINE和FONT_SHOW_SCROLL的
//方式分别设置多行显示和滚动显示
f_info->flags |= FONT_SHOW_PIXEL;
f_info->text_width = 300; //文本框显示宽度,用户可自行调整
f_info->text_height = 100; //文本框显示高度,用户可自行调整
//获取输入字符串宽高,并分别存放于f_info->string_width、f_info->string_height
font_textu_width(f_info, text_t, strlen(text_t));
//记录输入字符串宽高
int f_width = f_info->string_width;
int f_height = f_info->string_height;
//配置字符串信息
f_info->text_image_width = f_width;//(f_width + 31) / 32 * 32;
f_info->text_image_height = f_height;
f_info->text_image_stride = (f_width + 31) / 32 * 32 / 8;
//根据字符串长度申请buf
f_info->text_image_buf_size = f_info->text_image_stride * f_height;
f_info->text_image_buf = br28_zalloc(f_info->text_image_buf_size);
ASSERT(f_info->text_image_buf);
//将输入utf8字符串字模数据保存在f_info->text_image_buf
u16 f_len = font_textout_utf8(f_info, text_t, strlen(text_t), 0, 0);
pixbuf1 = f_info->text_image_buf;
/*以上也可以修改为font_text_out(FONT_ENCODE_UTF8, f_info, str, sizeof(str), 0, 0); //解析字库,结果放进f_info->text_image_buf*/
/*font_text_out函数的第一个参数为编码格式,可以修改为FONT_ENCODE_ANSI、FONT_ENCODE_UNICODE*/
/*分别显示内码与unicode编码格式的字符串*/
//创建字库显示任务,在(100, 200)的位置上显示字符串,颜色为蓝色
imb_create_text_task(100, 200, f_width, f_height, pixbuf1, 0x001f);