3. GUI自定义字库
3.1 GUI自定义字库概述
GT5G系列芯片是高通从传统固定字库芯片升级而来的新一代GUI资源芯片。与传统字库芯片只能使用出厂预置的固定字库不同,GT5G系列支持用户按需自定义配置字库资源,所有高通全系列字库均可在GT-HMI Designer中自由选用。
芯片支持三种字库类型:
- 点阵字库:体积小、渲染快,适合小尺寸屏幕和资源受限的场景
- 灰度字库:支持抗锯齿显示,文字边缘更平滑,适合中等分辨率屏幕
- 矢量字库:支持任意缩放不失真,适合高分辨率屏幕和需要动态调整字号的场景
字库覆盖中文、拉丁文、日文、韩文、阿拉伯文、泰文等多语种,开发者只需在上位机中勾选所需的语种、字号和字库类型,编译后通过烧录器写入芯片即可。字库之外的剩余存储空间可用于存放图片素材或用户自定义数据。
视频教程:
3.2 字库资源烧录
第一步:在 GT-HMI Designer 中选择所需的字库(语种、字号、字库类型),编译生成 resource.bin。
第二步:烧录步骤可参考本文 2.3 节。文件开始地址和缓冲区开始地址默认 0x000000 即可。如果需要烧录自定义的内容,可以将自定义内容与 resource.bin 合并在一起烧录,也可以在烧录 resource.bin 后单独烧录自定义内容,但是要在烧录时将文件开始地址偏移到 resource.bin 之后。
3.3 字库调用
1. 实现 SPI 读写的外部驱动函数:
/**
* @brief 发送读取函数
* @param sendbuf 发送数据的buff
* @param sendlen 发送数据长度
* @param receivebuf 读取数据的buff
* @param receivelen 读取数据长度
*/
unsigned char gt_read_data(unsigned char * sendbuf, unsigned char sendlen,
unsigned char * receivebuf, unsigned int receivelen)
{
unsigned int i;
Rom_csL; // 拉低片选cs,选中flash
for(i = 0; i < sendlen; i++)
{
SPI1_ReadWriteByte(sendbuf[i]); // 发送数据
}
for(i = 0; i < receivelen; i++)
{
receivebuf[i] = SPI1_ReadWriteByte(0x00); // 接收数据,保存到receivebuf[]
}
Rom_csH; // 拉高片选cs,空闲
return 1;
}
/**
* @brief SPI读取函数
* @param address 地址
* @param r_data_len 读取长度
* @param p_rbuf 数据保存地址
*/
unsigned char r_dat_bat(unsigned long address, unsigned long r_data_len,
unsigned char *p_rbuf)
{
#define _TX_DATA_LEN (4)
unsigned char tx_buf[_TX_DATA_LEN] = {0};
tx_buf[0] = 0x03; // 读取数据的命令
tx_buf[1] = (unsigned char)((address & 0xFF0000) >> 16);
tx_buf[2] = (unsigned char)((address & 0x00FF00) >> 8);
tx_buf[3] = (unsigned char)((address & 0x0000FF));
return gt_read_data(tx_buf, _TX_DATA_LEN, p_rbuf, r_data_len);
}
2. 字库初始化: 在调用字库前调用 GT_Font_Init() 函数进行字库初始化。函数返回值大于 0,并且不等于 0xFF 代表字库芯片初始化成功。
int ret = GT_Font_Init(); // 字库芯片初始化函数,返回大于0且非FF的值代表字库芯片初始成功
if (ret <= 0)
{
printf(">>>>>>>>>>>>>>>> GT_Font_Init error !!!\n");
return -1;
}
3. SPI 通信验证: 如果字库初始化失败,可以使用以下示例验证 SPI 通信。如果 tmp_buf 里面的数据是 0x00 或 0xFF,就表示 SPI 读写函数的实现有问题。亦或者是有规律的一组数字,前三位的最后一位不在 12-19 范围内也不是 C9,就需要排查一下 SPI 时序。
uint8_t tmp_buf[8] = {0};
tmp_buf[0] = 0x9F;
gt_read_data(tmp_buf, 1, tmp_buf, 8);
for(int i = 0; i < 8; i++)
{
printf("tmp_buf:%x\r\n", tmp_buf[i]);
}
4. 中文 16 点宋体调用示例:
// 中文
#define _USER_UNICODE_CHINESE 0 // 中文使用Unicode编码
#if _USER_UNICODE_CHINESE
unsigned int chinese_buf[] = {
0x554A, 0x963F, 0x57C3, // "啊阿埃" 的Unicode编码
0x56FD, 0x5BB6, 0x4EBA, // "国家人" 的Unicode编码
0x946B, 0x6DFC, 0x61FF, // "鑫淼懿" 的Unicode编码
};
#else
unsigned int chinese_buf[] = {
0xB0A1, 0xB0A2, 0xB0A3, // "啊阿埃" 的GBK编码
0xB9FA, 0xBCD2, 0xC8CB, // "国家人" 的GBK编码
0xF6CE, 0xEDB5, 0xDCB2, // "鑫淼懿" 的GBK编码
};
#endif
for(int i = 0; i < sizeof(chinese_buf)/sizeof(chinese_buf[0]); i++)
{
#if _USER_UNICODE_CHINESE
// 使用Unicode编码直接调用中文字符
GT_GetChinese(chinese_buf[i], GT_FAMILY_GB2312_16_ST, DZ_Data);
#else
// 使用GBK编码调用中文字符
GT_Set_Chinese_Charset_Type(1);
GT_GetChinese(chinese_buf[i], GT_FAMILY_GB2312_16_ST, DZ_Data);
GT_Set_Chinese_Charset_Type(0); // 恢复库函数调用的编码模式
#endif
fontDisplay_DZ(DZ_Data, x, y, 16, 16, 0x0000, 0xFFFF, 0);
x += 20;
}
x = 50;
y += 30;
5. 英文调用示例:
memset(DZ_Data, 0, sizeof(DZ_Data));
for(int i = 0; i < sizeof(ascii_buf)/sizeof(ascii_buf[0]); i++)
{
// 使用Unicode编码直接调用英文字符
GT_GetASCII(ascii_buf[i], GT_FAMILY_ASCII_8x16, DZ_Data);
fontDisplay_DZ(DZ_Data, x, y, 8, 16, 0x0000, 0xFFFF, 0);
x += 20;
if (x + 20 > 480)
{
x = 50;
y += 20;
}
}
x = 50;
y += 30;
6. 日文、韩文调用 API:
int GT_GetJapanese(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
int GT_GetKorean(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
用法与中文一致,根据编码调用即可。
7. 拉丁文、西里尔文、希腊文和希伯来文调用 API:
int GT_GetLatin(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
int GT_GetCyrillic(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
int GT_GetGreek(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
int GT_GetHebrew(unsigned long fontcode, unsigned int font_option, unsigned char* pbuffer);
用法与英文一致。
8. 阿拉伯文调用示例(需连字变换,从右向左书写):
// 阿拉伯文测试文本
unsigned short arabic_buf[] = {
0x0645, 0x0631, 0x062D, 0x0628, 0x0627, 0x0020,
0x0627, 0x0644, 0x0639, 0x0627, 0x0644, 0x0645,
};
// 阿拉伯文调用回调
static int _arabic_read_dot_font_cb(_gt_read_cb_param_st* read_cb)
{
if(!read_cb || !read_cb->convert || !read_cb->data_p) return -1;
font_convertor_st* convert = (font_convertor_st*)read_cb->convert;
return GT_GetArabic(read_cb->font_code, convert->font_option, read_cb->data_p);
}
memset(DZ_Data, 0, sizeof(DZ_Data));
font_convertor_st arabic_convertor = {
.fontcode = arabic_buf,
.code_len = sizeof(arabic_buf)/sizeof(arabic_buf[0]),
.fontsize = 16,
.fontgray = 1,
.font_option = GT_FAMILY_Arabic_16x16,
.thick = 16,
.data_p = DZ_Data,
.data_len = sizeof(DZ_Data),
.is_rev = 1, // 阿拉伯文从右向左书写,需要反向
.is_vec = 0,
.read_dot_font = _arabic_read_dot_font_cb,
};
int arabic_text_len = GT_Font_Code_Transform(&arabic_convertor);
for(int i = 0; i < arabic_text_len;)
{
memset(DZ_Data, 0, sizeof(DZ_Data));
int arabic_tmp = GT_Get_Font_Convertor_Data(&arabic_convertor, i);
int arabic_font_wigth = gt_font_get_word_width_figure_up(
&arabic_convertor.data_p[0], 16, 16, arabic_convertor.fontgray);
fontDisplay_DZ(&arabic_convertor.data_p[0], x, y, 16, 16, 0x0000, 0xFFFF, 0);
x += arabic_font_wigth;
i += arabic_tmp;
}
x = 50;
y += 30;
9. 泰文调用示例:
unsigned short thai_buf[] = {
0x0E2A, 0x0E27, 0x0E31, 0x0E2A, 0x0E14, 0x0E35,
0x0E0A, 0x0E32, 0x0E27, 0x0E42, 0x0E25, 0x0E01,
};
static int _thai_read_dot_font_cb(_gt_read_cb_param_st* read_cb)
{
if(!read_cb || !read_cb->convert || !read_cb->data_p) return -1;
font_convertor_st* convert = (font_convertor_st*)read_cb->convert;
return GT_GetThai(read_cb->font_code, convert->font_option, read_cb->data_p);
}
font_convertor_st thai_convertor = {
.fontcode = thai_buf,
.code_len = sizeof(thai_buf)/sizeof(thai_buf[0]),
.fontsize = 32,
.fontgray = 1,
.font_option = GT_FAMILY_Thai_32x32,
.thick = 32,
.data_p = DZ_Data,
.data_len = sizeof(DZ_Data),
.is_rev = 0,
.is_vec = 0,
.read_dot_font = _thai_read_dot_font_cb,
};
int thai_text_len = GT_Font_Code_Transform(&thai_convertor);
for(int i = 0; i < thai_text_len;)
{
memset(DZ_Data, 0, sizeof(DZ_Data));
int thai_tmp = GT_Get_Font_Convertor_Data(&thai_convertor, i);
int thai_font_wigth = gt_font_get_word_width_figure_up(
&thai_convertor.data_p[0], 32, 32, thai_convertor.fontgray);
fontDisplay_DZ(thai_convertor.data_p, x, y, 32, 32, 0x0000, 0xFFFF, 0);
x += thai_font_wigth;
i += thai_tmp;
}
x = 50;
y += 30;
10. 印地文调用示例(需连字变换,从右向左书写):
unsigned short hindi_buf[] = {
0x0928, 0x092E, 0x0938, 0x094D, 0x0924, 0x0947, 0x0020,
0x0926, 0x0941, 0x0928, 0x093F, 0x092F, 0x093E,
};
static int _hindi_read_dot_font_cb(_gt_read_cb_param_st* read_cb)
{
if(!read_cb || !read_cb->convert || !read_cb->data_p) return -1;
font_convertor_st* convert = (font_convertor_st*)read_cb->convert;
return GT_GetHindi(read_cb->font_code, convert->font_option, read_cb->data_p);
}
font_convertor_st hindi_convertor = {
.fontcode = hindi_buf,
.code_len = sizeof(hindi_buf)/sizeof(hindi_buf[0]),
.fontsize = 24,
.fontgray = 1,
.font_option = GT_FAMILY_Hindi_16x24,
.thick = 24,
.data_p = DZ_Data,
.data_len = sizeof(DZ_Data),
.is_rev = 1, // 印地文从右向左书写
.is_vec = 0,
.read_dot_font = _hindi_read_dot_font_cb,
};
int hindi_text_len = GT_Font_Code_Transform(&hindi_convertor);
int font_data_len = (16 / 8) * 24;
for(int i = 0; i < hindi_text_len; i++)
{
int hindi_font_wigth = gt_font_get_word_width_figure_up(
&hindi_convertor.data_p[i * font_data_len], 16, 24, hindi_convertor.fontgray);
fontDisplay_DZ(&hindi_convertor.data_p[i * font_data_len], x, y, 16, 24, 0x0000, 0xFFFF, 0);
x += hindi_font_wigth;
}
x = 50;
y += 30;


