第五章 LVGL 字库使用
第五章 LVGL 字库使用
LVGL 的字体功能是较为强大的: 支持 UTF-8 编码、图标字体、 自定义字体、 最高 8bpp的抗锯齿, 等等。值得注意的是, bpp 值越大, 字体的边缘会越平滑,但其对内存的占用就越多,在界面上进行字体渲染时,绘制速度也会越慢, 一般的项目, 采用 4bpp 就足够了。
1 启用 UTF-8 编码
LVGL 支持 2 种编码方式: 第一种是 ASCII 编码,这种编码只支持英文字符的显示; 第二种是 UTF-8 编码,这种编码可以支持全球所有字符的显示。 用户需要在 LVGL 工程中启用UTF-8 编码, 可以打开 lv_conf.h 文件, 修改 LV_TXT_ENC 配置项, 如下源码所示:
/* 为字符串选择字符编码.
* IDE 或编辑器应该具有相同的字符编码
* 1. - LV_TXT_ENC_UTF8
* 2. - LV_TXT_ENC_ASCII
* */
#define LV_TXT_ENC LV_TXT_ENC_UTF8
这里建议大家将 MDK 软件设置为 Chinese GB2312 编码, 以更好地兼容中文。
2 使用 LVGL 内置图标字体
图标字体是 web 前端中流行的一种技术,它以字体的形式,呈现出一个单色的图标。 在LVGL 中, 自带了许多常用图标字体, 这极大地方便了用户的界面开发。 大家需要使用这些图标字体, 可以打开lv_symbol_def.h文件, 查找相应的图标字体枚举, 所有枚举如下源码所示:
#define LV_SYMBOL_AUDIO "\xef\x80\x81" /*61441, 0xF001*/
#define LV_SYMBOL_VIDEO "\xef\x80\x88" /*61448, 0xF008*/
#define LV_SYMBOL_LIST "\xef\x80\x8b" /*61451, 0xF00B*/
#define LV_SYMBOL_OK "\xef\x80\x8c" /*61452, 0xF00C*/
#define LV_SYMBOL_CLOSE "\xef\x80\x8d" /*61453, 0xF00D*/
#define LV_SYMBOL_POWER "\xef\x80\x91" /*61457, 0xF011*/
#define LV_SYMBOL_SETTINGS "\xef\x80\x93" /*61459, 0xF013*/
#define LV_SYMBOL_HOME "\xef\x80\x95" /*61461, 0xF015*/
#define LV_SYMBOL_DOWNLOAD "\xef\x80\x99" /*61465, 0xF019*/
#define LV_SYMBOL_DRIVE "\xef\x80\x9c" /*61468, 0xF01C*/
#define LV_SYMBOL_REFRESH "\xef\x80\xa1" /*61473, 0xF021*/
#define LV_SYMBOL_MUTE "\xef\x80\xa6" /*61478, 0xF026*/
#define LV_SYMBOL_VOLUME_MID "\xef\x80\xa7" /*61479, 0xF027*/
#define LV_SYMBOL_VOLUME_MAX "\xef\x80\xa8" /*61480, 0xF028*/
#define LV_SYMBOL_IMAGE "\xef\x80\xbe" /*61502, 0xF03E*/
#define LV_SYMBOL_EDIT "\xef\x8C\x84" /*62212, 0xF304*/
#define LV_SYMBOL_PREV "\xef\x81\x88" /*61512, 0xF048*/
#define LV_SYMBOL_PLAY "\xef\x81\x8b" /*61515, 0xF04B*/
#define LV_SYMBOL_PAUSE "\xef\x81\x8c" /*61516, 0xF04C*/
#define LV_SYMBOL_STOP "\xef\x81\x8d" /*61517, 0xF04D*/
#define LV_SYMBOL_NEXT "\xef\x81\x91" /*61521, 0xF051*/
#define LV_SYMBOL_EJECT "\xef\x81\x92" /*61522, 0xF052*/
#define LV_SYMBOL_LEFT "\xef\x81\x93" /*61523, 0xF053*/
#define LV_SYMBOL_RIGHT "\xef\x81\x94" /*61524, 0xF054*/
#define LV_SYMBOL_PLUS "\xef\x81\xa7" /*61543, 0xF067*/
#define LV_SYMBOL_MINUS "\xef\x81\xa8" /*61544, 0xF068*/
#define LV_SYMBOL_EYE_OPEN "\xef\x81\xae" /*61550, 0xF06E*/
#define LV_SYMBOL_EYE_CLOSE "\xef\x81\xb0" /*61552, 0xF070*/
#define LV_SYMBOL_WARNING "\xef\x81\xb1" /*61553, 0xF071*/
#define LV_SYMBOL_SHUFFLE "\xef\x81\xb4" /*61556, 0xF074*/
#define LV_SYMBOL_UP "\xef\x81\xb7" /*61559, 0xF077*/
#define LV_SYMBOL_DOWN "\xef\x81\xb8" /*61560, 0xF078*/
#define LV_SYMBOL_LOOP "\xef\x81\xb9" /*61561, 0xF079*/
#define LV_SYMBOL_DIRECTORY "\xef\x81\xbb" /*61563, 0xF07B*/
#define LV_SYMBOL_UPLOAD "\xef\x82\x93" /*61587, 0xF093*/
#define LV_SYMBOL_CALL "\xef\x82\x95" /*61589, 0xF095*/
#define LV_SYMBOL_CUT "\xef\x83\x84" /*61636, 0xF0C4*/
#define LV_SYMBOL_COPY "\xef\x83\x85" /*61637, 0xF0C5*/
#define LV_SYMBOL_SAVE "\xef\x83\x87" /*61639, 0xF0C7*/
#define LV_SYMBOL_CHARGE "\xef\x83\xa7" /*61671, 0xF0E7*/
#define LV_SYMBOL_PASTE "\xef\x83\xAA" /*61674, 0xF0EA*/
#define LV_SYMBOL_BELL "\xef\x83\xb3" /*61683, 0xF0F3*/
#define LV_SYMBOL_KEYBOARD "\xef\x84\x9c" /*61724, 0xF11C*/
#define LV_SYMBOL_GPS "\xef\x84\xa4" /*61732, 0xF124*/
#define LV_SYMBOL_FILE "\xef\x85\x9b" /*61787, 0xF158*/
#define LV_SYMBOL_WIFI "\xef\x87\xab" /*61931, 0xF1EB*/
#define LV_SYMBOL_BATTERY_FULL "\xef\x89\x80" /*62016, 0xF240*/
#define LV_SYMBOL_BATTERY_3 "\xef\x89\x81" /*62017, 0xF241*/
#define LV_SYMBOL_BATTERY_2 "\xef\x89\x82" /*62018, 0xF242*/
#define LV_SYMBOL_BATTERY_1 "\xef\x89\x83" /*62019, 0xF243*/
#define LV_SYMBOL_BATTERY_EMPTY "\xef\x89\x84" /*62020, 0xF244*/
#define LV_SYMBOL_USB "\xef\x8a\x87" /*62087, 0xF287*/
#define LV_SYMBOL_BLUETOOTH "\xef\x8a\x93" /*62099, 0xF293*/
#define LV_SYMBOL_TRASH "\xef\x8B\xAD" /*62189, 0xF2ED*/
#define LV_SYMBOL_BACKSPACE "\xef\x95\x9A" /*62810, 0xF55A*/
#define LV_SYMBOL_SD_CARD "\xef\x9F\x82" /*63426, 0xF7C2*/
#define LV_SYMBOL_NEW_LINE "\xef\xA2\xA2" /*63650, 0xF8A2*/
#define LV_SYMBOL_DUMMY "\xEF\xA3\xBF"
#define LV_SYMBOL_BULLET "\xE2\x80\xA2" /*20042, 0x2022*
当用户调用上述的图标字体枚举, 它们将显示成图标, 如下图所示:
接下来,我们介绍图标字体的使用方法, 示例代码如下:
void lv_mainstart(void)
{lv_obj_t *label = lv_label_create(lv_scr_act());lv_label_set_text(label, LV_SYMBOL_AUDIO"AUDIO");
}
由上述源码可知,图标字体的使用方法很简单, 用户只需要在设置文本的函数中直接调用相应的枚举即可, 示例代码的效果如下图所示:
3 使用 LVGL 内部字库
LVGL 提供了一套内置的字库,这些字库在移植的时候已经被添加到工程当中, 我们打开Middlewares/lvgl/src/font 分组, 即可找到这些字库文件, 如下图所示:
接下来,我们介绍 LVGL 内部字库的使用流程:
1. 使能字库
打开 lv_conf.h 文件, 将所需要使用的内部字库使能(宏定义置 1) , 如下图所示:
2.调用字库
使能了内部字库之后,用户就可以直接在字体设置函数中调用相应的字库了。这里我们结合源码,帮助大家理解内部字库的调用, 示例代码如下:
void lv_mainstart(void)
{lv_obj_t* label = lv_label_create(lv_scr_act());lv_obj_set_style_text_font(label,&lv_font_montserrat_16,LV_STATE_DEFAULT);lv_label_set_text(label,"Hello ALIENTEK!!!!");
}
在上述代码中,调用了 lv_obj_set_style_text_font 函数,并在该函数中设置了 16 号字体( lv_font_montserrat_16) , 如果大家需要设置其他的内部字体,只需要修改一下后缀即可,例如: 18 号字体为 lv_font_montserrat_18,以此类推。 值得注意的是,字号越大,文字越大,但其占用的内存也越多。示例代码的效果如下图所示:
4 使用自定义字库
在 LVGL 中,用户需要使用自定义的字库,其实现方法可分为两类:
① 通过 C 语言数组(内部读取) ;
② 通过文件系统读取字库(外部读取) 。
4.1 C 语言数组字库(内部)
使用 C语言数组的方式来读取字库是非常便捷的,工程中需要配置的地方很少,这对于初学者来说非常友好。 接下来, 我们介绍三种使用 C 语言数组读取字库的方法:
方法一:
使用 LVGL 官方的在线字体转换工具(网址: https://lvgl.io/tools/fontconverter) , 将字库文件(例如 TTF) 转换成 C 语言数组字体文件, 然后将其添加到工程中, 声明字体后即可调用。 值得注意的是, 由于该工具是在线的,且服务器在国外, 因此有可能出现转换失败的情况。当我们打开上述的转换工具网址后,界面如下图所示(实际页面没有红色的注释) :
由上图可知,使用在线转换工具生成字体一共需要七步:
① 在“Name”选项中填入字体名称。 注意: 该名称在声明字体的时候需要用到,请不要使用中文名称;
② 在“Size”选项中填入字体的尺寸,这里是以像素为单位的;
③ 在“Bpp”选项中选择像素深度, 注意: 该值越大,则抗锯齿效果越好,但是对内存的占用也会越高,一般的工程选择 4bbp 即可;
④ 选择字体文件,例如 ttf、 otf 格式的文件;
⑤ 在“Range”选项中填入文字编码范围, 以确定字体的转换范围。基本汉字的编码范围是 0x4E00-0x9FA5, 数字、拉丁字母、标点符号的编码范围是 0x20-0x7E,这两个范围内已经涵盖了两万多个字符, 可以满足绝大部分的使用场景。 关于文字的编码,大家感兴趣的话可以在网上了解一下。 注意: 转换的范围越大,字库所占用的内存就越高, 在该选项中,建议大家只填 0x20-0x7E。
⑥ 在“Symbols”选项中直接填入需要转换的文字。我们一般会将需要转换的汉字填入该选项;
⑦ 点击“Convert”,即可生成字体文件(后缀为.c) 。
当我们得到了字体文件之后,需要将其添加到工程中,然后声明字体即可调用,示例代码如下:
LV_FONT_DECLARE(my_Font14) /* 声明字体 */void lv_mainstart(void)
{lv_obj_t *font_label = lv_label_create(lv_scr_act());lv_obj_set_style_text_font(font_label, &my_Font14, LV_STATE_DEFAULT);lv_label_set_text(font_label, "你好");lv_obj_center(font_label);
}
方法二:
利用离线字体转换软件(V0.5 版本) , 将中文字库转化为 C 语言数组文件。 在这里, 我们由衷地感谢网友【阿里】 , 其开发的离线转换软件可以帮助用户轻松地生成 LVGL字库, 大家可以在他的博客网址(http://dz.lfly.xyz/forum.php) 中下载字体转换软件。
接下来,我们介绍该软件的使用方法:
1. 打开 LvglFontTool V0.5 软件,进入软件主界面后点击“选择字体”, 如下图所示:
2. 在弹窗中选择所需字体, 如下图所示:
3. 加入常用汉字, 如下图所示:
4.选择 LVGL 版本、 字体类型,设置字体名称, 如下图所示:
5. 点击“开始转换” ,在弹窗中选择文件路径并点击“保存” 。等待转换完成,将会得到一个.c 文件, 该文件即字体文件。在得到字体文件之后,我们将其添加到工程中,然后声明字体即可调用。
方法三:
利用离线字体转换软件(V0.4 版本) , 将中文字库转化为 C 语言数组文件。 与方法二不同的是,我们此处使用的是自选的 TTF 字体文件(V0.4 版本软件支持该功能) , 具体的使用方法如下:
1. 打开 LvglFontTool V0.4 软件,进入软件主界面后点击“选择字体”,如下图所示:
2. 在弹窗中选择所需的 TTF 字体, 设置字体大小, 如下图所示:
3. 添加常用的汉字,如下图所示:
4. 选择 LVGL 版本、字体类型,设置字体名称,如下图所示:
5. 点击“开始转换”, 等待转换完成后, 点击“保存” 即可得到一个.c 文件,该文件即字体文件。在得到字体文件之后,我们将其添加到工程中,然后声明字体即可调用
4.2 文件系统读取字库(外部)
在上一小节中,我们都是使用 C语言数组的方式生成字库,该方法虽然简单,但其也存在一定的弊端:如果 MCU 的内存较小,而工程中需要使用的文字较多, 此时, 再用 C 语言数组的方式生成字库就不太现实了。为了解决上述的问题, 下面给大家介绍如何使用文件系统来读取外部字体。 我们这里用到的依旧是网友【阿里】的离线字体转换软件(V0.5 版本) , 外部字库的使用流程如下:
1. 打开 LvglFontTool V0.5 软件,进入软件主界面后点击“选择字体”,如下图所示:
2. 在弹窗中选择所需字体,如下图所示:
3. 加入常用汉字,如下图所示:
4. 选择版本、类型(XBF,外部 bin 文件),设置字体名称, 如下图所示:
5. 点击“开始转换”,在弹窗中选择文件路径并点击“保存”。等待转换完成, 将会得到两个文件,它们的后缀分别为.c 和.bin。 我们把.c 文件添加到工程中,而.bin 文件则放到 SD 卡里面(建议路径: 根目录→SYSTEM→LVFONT) 。
6. 打 开 工 程 , 找 到 上 一 步 添 加 的 字 体 文 件 , 修 改__user_font_getdata 函数, 如下源码所示:
static uint8_t *__user_font_getdata(int offset, int size){/* 如字模保存在 SPI FLASH, SPIFLASH_Read(__g_font_buf,offset,size);如字模已加载到 SDRAM,直接返回偏移地址即可如:return (uint8_t*)(sdram_fontddr+offset); */norflash_ex_read(__g_font_buf,ftinfo.lvgl_12addr +offset,size);return __g_font_buf;
}
7. 修改 fonts.h 文件, 如下源码所示:
/* 字体信息保存首地址
* 占 41 个字节,第 1 个字节用于标记字库是否存在.后续每 8 个字节一组,分别保存起始地址和文件大小
*/
extern uint32_t FONTINFOADDR;
/* 字库信息结构体定义
* 用来保存字库基本信息,地址,大小等
*/
typedef __PACKED_STRUCT
{uint8_t fontok; /* 字库存在标志, 0XAA,字库正常;其他,字库不存在 */uint32_t ugbkaddr; /* unigbk 的地址 */uint32_t ugbksize; /* unigbk 的大小 */uint32_t f12addr; /* gbk12 地址 */uint32_t gbk12size; /* gbk12 的大小 */uint32_t f16addr; /* gbk16 地址 */uint32_t gbk16size; /* gbk16 的大小 */uint32_t f24addr; /* gbk24 地址 */uint32_t gbk24size; /* gbk24 的大小 */uint32_t f32addr; /* gbk32 地址 */uint32_t gbk32size; /* gbk32 的大小 */uint32_t lvgl_12addr; /* LVGL12 地址 */uint32_t lvgl_12size; /* LVGL12 的大小 */uint32_t lvgl_24addr; /* LVGL24 地址 */uint32_t lvgl_24size; /* LVGL24 的大小 */uint32_t lvgl_36addr; /* LVGL36 地址 */uint32_t lvgl_36size; /* LVGL36 的大小 */
} _font_info;
8. 修改 fonts.c 文件中的 FONT_GBK_PATH 和 FONT_UPDATE_REMIND_TBL 数组, 如下源码所示:
/* 字库存放在磁盘中的路径 */
char *const FONT_GBK_PATH[8] =
{"/SYSTEM/FONT/UNIGBK.BIN", /* UNIGBK.BIN 的存放位置 */"/SYSTEM/FONT/GBK12.FON", /* GBK12 的存放位置 */"/SYSTEM/FONT/GBK16.FON", /* GBK16 的存放位置 */"/SYSTEM/FONT/GBK24.FON", /* GBK24 的存放位置 */"/SYSTEM/FONT/GBK32.FON", /* GBK32 的存放位置 */"/SYSTEM/LVFONT/Font12.BIN", /* Font12 的存放位置 */"/SYSTEM/LVFONT/Font24.BIN", /* Font24 的存放位置 */"/SYSTEM/LVFONT/Font36.BIN", /* Font36 的存放位置 */
};
/* 更新时的提示信息 */
char *const FONT_UPDATE_REMIND_TBL[8] =
{"Updating UNIGBK.BIN", /* 提示正在更新 UNIGBK.bin */"Updating GBK12.FON ", /* 提示正在更新 GBK12 */"Updating GBK16.FON ", /* 提示正在更新 GBK16 */"Updating GBK24.FON ", /* 提示正在更新 GBK24 */"Updating GBK32.FON ", /* 提示正在更新 GBK32 */"Updating Font12.BIN", /* 提示正在更新 Font12 */"Updating Font24.BIN", /* 提示正在更新 Font24 */"Updating Font36.BIN", /* 提示正在更新 Font36 */
};
9. 修改 fonts.c 文件中的 fonts_update_fontx 函数, 如下源码所示:
/**
* @brief 更新某一个字库
* @param x, y : 提示信息的显示地址
* @param size : 提示信息字体大小
* @param fpath : 字体路径
* @param fx : 更新的内容
* @arg 0, ungbk;
* @Arg 1, gbk12;
* @arg 2, gbk16;
* @arg 3, gbk24;
* @arg 4, gbk32;
* @param color : 字体颜色
* @retval 0, 成功; 其他, 错误代码;
*/
static uint8_t fonts_update_fontx( uint16_t x,uint16_t y,uint8_t size,uint8_t *fpath,uint8_t fx,uint16_t color)
{uint32_t flashaddr = 0;FIL *fftemp;uint8_t *tempbuf;uint8_t res;uint16_t bread;uint32_t offx = 0;uint8_t rval = 0;fftemp = (FIL *)mymalloc(SRAMIN, sizeof(FIL)); /* 分配内存 */if (fftemp == NULL)rval = 1;tempbuf = mymalloc(SRAMIN, 4096); /* 分配 4096 个字节空间 */if (tempbuf == NULL)rval = 1;res = f_open(fftemp, (const TCHAR *)fpath, FA_READ);if (res)rval = 2; /* 打开文件失败 */if (rval == 0){switch (fx){case 0: /* 更新 UNIGBK.BIN *//* 信息头之后,紧跟 UNIGBK 转换码表 */ftinfo.ugbkaddr = FONTINFOADDR + sizeof(ftinfo);ftinfo.ugbksize = fftemp->obj.objsize; /* UNIGBK 大小 */flashaddr = ftinfo.ugbkaddr;break;case 1: /* 更新 GBK12.BIN *//* UNIGBK 之后,紧跟 GBK12 字库 */ftinfo.f12addr = ftinfo.ugbkaddr + ftinfo.ugbksize;ftinfo.gbk12size = fftemp->obj.objsize; /* GBK12 字库大小 */flashaddr = ftinfo.f12addr; /* GBK12 的起始地址 */break;case 2: /* 更新 GBK16.BIN *//* GBK12 之后,紧跟 GBK16 字库 */ftinfo.f16addr = ftinfo.f12addr + ftinfo.gbk12size;ftinfo.gbk16size = fftemp->obj.objsize; /* GBK16 字库大小 */flashaddr = ftinfo.f16addr; /* GBK16 的起始地址 */break;case 3: /* 更新 GBK24.BIN *//* GBK16 之后,紧跟 GBK24 字库 */ftinfo.f24addr = ftinfo.f16addr + ftinfo.gbk16size;ftinfo.gbk24size = fftemp->obj.objsize; /* GBK24 字库大小 */flashaddr = ftinfo.f24addr; /* GBK24 的起始地址 */break;case 4: /* 更新 GBK32.BIN *//* GBK24 之后,紧跟 GBK32 字库 */ftinfo.f32addr = ftinfo.f24addr + ftinfo.gbk24size;ftinfo.gbk32size = fftemp->obj.objsize; /* GBK32 字库大小 */flashaddr = ftinfo.f32addr; /* GBK32 的起始地址 */break;case 5:/* 更新 LVGL12.BIN */ (1)ftinfo.lvgl_12addr=ftinfo.f32addr+ftinfo.gbk32size;ftinfo.lvgl_12size=fftemp->obj.objsize;flashaddr=ftinfo.lvgl_12addr;break;case 6:/* 更新 LVGL24.BIN */ (2)ftinfo.lvgl_24addr=ftinfo.lvgl_12addr+ftinfo.lvgl_12size;ftinfo.lvgl_24size=fftemp->obj.objsize;flashaddr=ftinfo.lvgl_24addr;break;case 7:/* 更新 LVGL36.BIN */ (3)ftinfo.lvgl_36addr=ftinfo.lvgl_24addr+ftinfo.lvgl_24size;ftinfo.lvgl_36size=fftemp->obj.objsize;flashaddr=ftinfo.lvgl_36addr;break;}while (res == FR_OK) /* 死循环执行 */{res = f_read(fftemp, tempbuf, 4096, (UINT *)&bread); /* 读取数据 */if (res != FR_OK)break; /* 执行错误 *//* 从 0 开始写入 bread 个数据 */norflash_ex_write(tempbuf, offx + flashaddr, bread);offx += bread;/* 进度显示 */fonts_progress_show(x, y, size, fftemp->obj.objsize, offx, color);if (bread != 4096)break; /* 读完了. */}f_close(fftemp);}myfree(SRAMIN, fftemp); /* 释放内存 */myfree(SRAMIN, tempbuf); /* 释放内存 */return res;
}
上述源码中的 (1)~(3)处是新增的内容。
10. 修改 fonts.c 文件中的 fonts_update_font 函数, 如下源码所示:
/**
* @brief 更新字体文件
* @note 所有字库一起更新(UNIGBK,GBK12,GBK16,GBK24,GBK32)
* @param x, y : 提示信息的显示地址
* @param size : 提示信息字体大小
* @param src : 字库来源磁盘
* @arg "0:", SD 卡;
* @Arg "1:", FLASH 盘
* @arg "2:", U 盘
* @param color : 字体颜色
* @retval 0, 成功; 其他, 错误代码;
*/
uint8_t fonts_update_font( uint16_t x,uint16_t y,uint8_t size,uint8_t *src,uint16_t color)
{uint8_t *pname;uint32_t *buf;uint8_t res = 0;uint16_t i, j;FIL *fftemp;uint8_t rval = 0;res = 0XFF;ftinfo.fontok = 0XFF;pname = mymalloc(SRAMIN, 100); /* 申请 100 字节内存 */buf = mymalloc(SRAMIN, 4096); /* 申请 4K 字节内存 */fftemp = (FIL *)mymalloc(SRAMIN, sizeof(FIL)); /* 分配内存 */if (buf == NULL || pname == NULL || fftemp == NULL){myfree(SRAMIN, fftemp);myfree(SRAMIN, pname);myfree(SRAMIN, buf);return 5; /* 内存申请失败 */}/* 先查找文件 UNIGBK,GBK12,GBK16,GBK24,GBK32,LVGL12.BIN,LVGL24.BIN,LVGL36BIN 是否正常 */for (i = 0; i < 8; i++) (1){strcpy((char *)pname, (char *)src); /* copy src 内容到 pname */strcat((char *)pname, (char *)FONT_GBK_PATH[i]); /* 追加具体文件路径 */res = f_open(fftemp, (const TCHAR *)pname, FA_READ);/* 尝试打开 */if (res){rval |= 1 << 7; /* 标记打开文件失败 */break; /* 出错了,直接退出 */}}myfree(SRAMIN, fftemp); /* 释放内存 */if (rval == 0) /* 字库文件都存在. */{/* 提示正在擦除扇区 */lcd_show_string(x, y, 240, 320, size, "Erasing sectors... ", color);for (i = 0; i < FONTSECSIZE; i++) /* 先擦除字库区域,提高写入速度 */{/* 进度显示 */fonts_progress_show(x + 20 * size / 2, y, size, FONTSECSIZE,i, color);/* 读出整个扇区的内容 */norflash_ex_read((uint8_t *)buf, ((FONTINFOADDR /4096)+i) * 4096, 4096);for (j = 0; j < 1024; j++) /* 校验数据 */{if (buf[j] != 0XFFFFFFFF)break; /* 需要擦除 */}if (j != 1024){/* 需要擦除的扇区 */norflash_ex_erase_sector((FONTINFOADDR / 4096) + i);}}/* 依次更新 UNIGBK,GBK12,GBK16,GBK24,GBK32,LVGL12.BIN,LVGL24.BIN,LVGL36BIN */for (i = 0; i < 8; i++){lcd_show_string(x, y, 240, 320, size,FONT_UPDATE_REMIND_TBL[i], color);strcpy((char *)pname, (char *)src);strcat((char *)pname, (char *)FONT_GBK_PATH[i]);res = fonts_update_fontx(x + 20 * size / 2, y, size,pname, i, color);if (res){myfree(SRAMIN, buf);myfree(SRAMIN, pname);return 1 + i;}}/* 全部更新好了 */ftinfo.fontok = 0XAA;/* 保存字库信息 */norflash_ex_write((uint8_t *)&ftinfo, FONTINFOADDR, sizeof(ftinfo));}myfree(SRAMIN, pname); /* 释放内存 */myfree(SRAMIN, buf);return rval; /* 无错误. */
}
上述源码中,标识 (1)代表的是新增的内容。
11. 打开 lv_conf.h 文件,找到 LV_FONT_CUSTOM_DECLARE 配置项, 声明该字体, 如下源码所示:
#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(Font12)
12. 编写示例代码:
void lv_mainstart(void)
{lv_obj_t* label = lv_label_create(lv_scr_act());lv_obj_set_style_text_font(label,& Font12,LV_STATE_DEFAULT);lv_label_set_text(label,"Hello ALIENTEK!!!!");
}
示例代码效果如下图所示: