准备工具,LvglFontTool v0.4

能运行LVGL8.2模拟器的codeblocks工程(百问网的LVGL模拟器工程)

========================================================================

===========================外部BIN文件方案================================

打开LvglFontTool v0.4

点加入所有汉字,如果是写到单片机里,建议使用常用汉字或者是自定义写入某些汉字

然后选择生成类型

选择头文件路径,我这里是模拟器,请按你自己的路径设置

设置字体名字,这个随意

然后选择字体,这里可以直接去控制面板复制到工具的根目录

点击确定

点击开始转换,选择模拟器工程里,我选的是根目录,方便找,但是乱了点

然后进codeblock,添加生成的字库.C文件到工程里

然后添加文件系统lv_port_fs.c文件(空白的)

文件内容如下,直接复制进去

/*** @file lv_port_fs.c**//*Copy this file as "lv_port_fs.c" and set this value to "1" to enable content*/
#if 1/**********************      INCLUDES*********************/
#include "lv_port_fs.h"
#if USE_FATFS_FILE_SYSTEM==1
#include "fatfs/ff.h"
#endif
#include "../lvgl/lvgl.h"
#include "stdio.h"/**********************      DEFINES*********************//***********************      TYPEDEFS**********************//***********************  STATIC PROTOTYPES**********************/
static void fs_init(void);
#if USE_PC_FILE_SYSTEM==1
static lv_fs_res_t fs_open(lv_fs_drv_t *drv, void *file_p, const char *path,lv_fs_mode_t mode);
static lv_fs_res_t fs_close(lv_fs_drv_t *drv, void *file_p);
static lv_fs_res_t fs_read(lv_fs_drv_t *drv, void *file_p, void *buf,uint32_t btr, uint32_t *br);
static lv_fs_res_t fs_write(lv_fs_drv_t *drv, void *file_p, const void *buf,uint32_t btw, uint32_t *bw);
static lv_fs_res_t fs_seek(lv_fs_drv_t *drv, void *file_p, uint32_t pos,lv_fs_whence_t whence);
static lv_fs_res_t fs_size(lv_fs_drv_t *drv, void *file_p, uint32_t *size_p);
static lv_fs_res_t fs_tell(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p);static void* fs_dir_open(lv_fs_drv_t *drv, void *rddir_p, const char *path);
static lv_fs_res_t fs_dir_read(lv_fs_drv_t *drv, void *rddir_p, char *fn);
static lv_fs_res_t fs_dir_close(lv_fs_drv_t *drv, void *rddir_p);
#endif
/***********************  STATIC VARIABLES**********************//*********************** GLOBAL PROTOTYPES**********************//***********************      MACROS**********************//***********************   GLOBAL FUNCTIONS**********************/
#if USE_PC_FILE_SYSTEM==1
bool pcfs_ready(lv_fs_drv_t *drv);
static void* pcfs_open(lv_fs_drv_t *drv, const char *fn, lv_fs_mode_t mode);
static lv_fs_res_t pcfs_write(struct _lv_fs_drv_t *drv, void *file_p,const void *buf, uint32_t btw, uint32_t *bw);
static lv_fs_res_t pcfs_read(lv_fs_drv_t *drv, void *file_p, void *buf,uint32_t btr, uint32_t *br);
static lv_fs_res_t pcfs_close(lv_fs_drv_t *drv, void *file_p);
static lv_fs_res_t pcfs_seek(lv_fs_drv_t *drv, void *file_p, uint32_t pos,lv_fs_whence_t whence);
static lv_fs_res_t pcfs_tell(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p);
#endif
void lv_port_fs_init(void) {/*----------------------------------------------------* Initialize your storage device and File System* -------------------------------------------------*/fs_init();/*---------------------------------------------------* Register the file system interface in LVGL*--------------------------------------------------*/
#if USE_FATFS_FILE_SYSTEM==1/*Add a simple drive to open images*/static lv_fs_drv_t fs_drv;lv_fs_drv_init(&fs_drv);/*Set up fields...*/fs_drv.letter = 'S';fs_drv.open_cb = fs_open;fs_drv.close_cb = fs_close;fs_drv.read_cb = fs_read;fs_drv.write_cb = fs_write;fs_drv.seek_cb = fs_seek;fs_drv.tell_cb = fs_tell;fs_drv.dir_close_cb = fs_dir_close;fs_drv.dir_open_cb = fs_dir_open;fs_drv.dir_read_cb = fs_dir_read;lv_fs_drv_register(&fs_drv);
#endif#if USE_PC_FILE_SYSTEM==1static lv_fs_drv_t pcfs_drv; /*A driver descriptor*/lv_fs_drv_init(&pcfs_drv);pcfs_drv.user_data = NULL;pcfs_drv.letter = 'S';pcfs_drv.ready_cb = pcfs_ready;pcfs_drv.write_cb = pcfs_write;pcfs_drv.open_cb = pcfs_open;pcfs_drv.close_cb = pcfs_close;pcfs_drv.read_cb = pcfs_read;pcfs_drv.seek_cb = pcfs_seek;pcfs_drv.tell_cb = pcfs_tell;lv_fs_drv_register(&pcfs_drv);
#endif
}/***********************   STATIC FUNCTIONS**********************//*Initialize your Storage device and File system.*/
static void fs_init(void) {/*E.g. for FatFS initialize the SD card and FatFS itself*/
#if USE_FATFS_FILE_SYSTEM==1sfc_init();#endif/*You code here*/
}#if USE_PC_FILE_SYSTEM==1
//文件系统是否准备好被回调函数pcfs_ready
bool pcfs_ready(lv_fs_drv_t *drv) {(void) drv; /*Unused*/return true;  //这里仅返回true,如果是嵌入式,则是返回嵌入式文件系统挂载成功与否的标志
}
//打开文件被回调的函数pcfs_open
static void* pcfs_open(lv_fs_drv_t *drv, const char *fn, lv_fs_mode_t mode) {(void) drv; /*Unused*/errno = 0;const char *flags = "";if (mode == LV_FS_MODE_WR)flags = "wb";else if (mode == LV_FS_MODE_RD)flags = "rb";else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))flags = "a+";/*Make the path relative to the current directory (the projects root folder)*/char buf[256];sprintf(buf, "./%s", fn);return fopen(buf, flags);
}
//写入文件被回调的函数pcfs_write
static lv_fs_res_t pcfs_write(struct _lv_fs_drv_t *drv, void *file_p,const void *buf, uint32_t btw, uint32_t *bw) {(void) drv; /*Unused*/*bw = (uint32_t) fwrite(buf, 1, btw, file_p);return LV_FS_RES_OK;
}
//读取文件被回调的函数pcfs_read
static lv_fs_res_t pcfs_read(lv_fs_drv_t *drv, void *file_p, void *buf,uint32_t btr, uint32_t *br) {(void) drv; /*Unused*///pc_file_t* fp = file_p;        /*Just avoid the confusing casings*/*br = (uint32_t) fread(buf, 1, btr, file_p);return LV_FS_RES_OK;
}
//关闭文件被回调的函数pcfs_close
static lv_fs_res_t pcfs_close(lv_fs_drv_t *drv, void *file_p) {(void) drv; /*Unused*/return fclose(file_p);
}
//移动文件位置被回调的函数pcfs_seek
static lv_fs_res_t pcfs_seek(lv_fs_drv_t *drv, void *file_p, uint32_t pos,lv_fs_whence_t whence) {(void) drv; /*Unused*/return fseek(file_p, pos, whence);
}
//获取文件位置被回调的函数pcfs_tell
static lv_fs_res_t pcfs_tell(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p) {(void) drv; /*Unused*/*pos_p = ftell(file_p);return LV_FS_RES_OK;
}
#endif#if USE_FATFS_FILE_SYSTEM==1/*** Open a file* @param drv       pointer to a driver where this function belongs* @param path      path to the file beginning with the driver letter (e.g. S:/folder/file.txt)* @param mode      read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR* @return          a file descriptor or NULL on error*/
static lv_fs_res_t fs_open(lv_fs_drv_t *drv, void *file_p, const char *path,lv_fs_mode_t mode)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/************************************************* 在这里,我们需要先进行设备的判断,因为我们实际上* 可能不只有一个设备,而且LVGL里使用letter(即单个字符)* 作为驱动号* 而在FatFS里使用VOLUME_STR(字符串)或者一个字节的pdrv* 驱动号,使用前要进行转换。** 有一种方便的方法,就是上面提到的user_data,我们可以把* VOLUME_STR提前装入user_data,那我们的程序进行判断时* 耦合度会更低,在更多设备时,这种方法会更方便*************************************************/char *path_buf = NULL;uint8_t opt_mode = 0;uint16_t path_len = strlen(path);// 根据传入的letter判断是什么存储设备switch (drv->letter){case 'S':       // SD cardpath_buf = (char*) lv_mem_alloc(sizeof(char) * (path_len + 4));sprintf(path_buf, "SD:/%s", path);break;case 'F':       // SPI FALSHpath_buf = (char*) lv_mem_alloc(sizeof(char) * (path_len + 6));sprintf(path_buf, "SPIF:/%s", path);break;default:printf("No drive %c\n", drv->letter);return LV_FS_RES_NOT_EX;}/* 文件操作方法,将FatFS的转换成LVGL的操作方法 */if (mode == LV_FS_MODE_WR){opt_mode = FA_OPEN_ALWAYS | FA_WRITE;}else if (mode == LV_FS_MODE_RD){opt_mode = FA_OPEN_EXISTING | FA_READ;}else if (mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)){opt_mode = FA_WRITE | FA_READ;}/* 调用FatFs的函数 */FRESULT fres = f_open((FIL*) file_p, path_buf, opt_mode);if (fres != FR_OK){printf("f_open error (%d)\n", fres);res = LV_FS_RES_NOT_IMP;}elseres = LV_FS_RES_OK;lv_mem_free(path_buf);return res;
}/*** Close an opened file* @param drv       pointer to a driver where this function belongs* @param file_p    pointer to a file_t variable. (opened with lv_ufs_open)* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_close(lv_fs_drv_t *drv, void *file_p)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}/*** Read data from an opened file* @param drv       pointer to a driver where this function belongs* @param file_p    pointer to a file_t variable.* @param buf       pointer to a memory block where to store the read data* @param btr       number of Bytes To Read* @param br        the real number of read bytes (Byte Read)* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_read(lv_fs_drv_t *drv, void *file_p, void *buf,uint32_t btr, uint32_t *br)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}/*** Write into a file* @param drv       pointer to a driver where this function belongs* @param file_p    pointer to a file_t variable* @param buf       pointer to a buffer with the bytes to write* @param btr       Bytes To Write* @param br        the number of real written bytes (Bytes Written). NULL if unused.* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_write(lv_fs_drv_t *drv, void *file_p, const void *buf,uint32_t btw, uint32_t *bw)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}/*** Set the read write pointer. Also expand the file size if necessary.* @param drv       pointer to a driver where this function belongs* @param file_p    pointer to a file_t variable. (opened with lv_ufs_open )* @param pos       the new position of read write pointer* @param whence    tells from where to interpret the `pos`. See @lv_fs_whence_t* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_seek(lv_fs_drv_t *drv, void *file_p, uint32_t pos,lv_fs_whence_t whence)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}
/*** Give the position of the read write pointer* @param drv       pointer to a driver where this function belongs* @param file_p    pointer to a file_t variable.* @param pos_p     pointer to to store the result* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_tell(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}/*** Initialize a 'lv_fs_dir_t' variable for directory reading* @param drv       pointer to a driver where this function belongs* @param path      path to a directory* @return          pointer to the directory read descriptor or NULL on error*/
static void* fs_dir_open(lv_fs_drv_t *drv, void *rddir_p, const char *path)
{lv_fs_res_t dir = NULL;/*Add your code here*///dir = ...           /*Add your code here*/return dir;
}/*** Read the next filename form a directory.* The name of the directories will begin with '/'* @param drv       pointer to a driver where this function belongs* @param rddir_p   pointer to an initialized 'lv_fs_dir_t' variable* @param fn        pointer to a buffer to store the filename* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_dir_read(lv_fs_drv_t *drv, void *rddir_p, char *fn)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}/*** Close the directory reading* @param drv       pointer to a driver where this function belongs* @param rddir_p   pointer to an initialized 'lv_fs_dir_t' variable* @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum*/
static lv_fs_res_t fs_dir_close(lv_fs_drv_t *drv, void *rddir_p)
{lv_fs_res_t res = LV_FS_RES_NOT_IMP;/*Add your code here*/return res;
}
#endif#else /*Enable this file at the top*//*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

添加lv_prot_fs.h文件,依旧是放在工程根目录

内容如下

/*** @file lv_port_fs.h**//*Copy this file as "lv_port_fs.h" and set this value to "1" to enable content*/
#if 1#ifndef LV_PORT_FS_H
#define LV_PORT_FS_H#ifdef __cplusplus
extern "C" {
#endif/**********************      INCLUDES*********************/
#include "../lvgl/lvgl.h"/**********************      DEFINES*********************/
//使用PC文件系统
#define USE_PC_FILE_SYSTEM 1
//使用FATFS文件系统
#define USE_FATFS_FILE_SYSTEM 0
/***********************      TYPEDEFS**********************//*********************** GLOBAL PROTOTYPES**********************//***********************      MACROS**********************/#ifdef __cplusplus
} /*extern "C"*/
#endif#endif /*LV_PORT_FS_H*/#endif /*Disable/Enable content*/

接下来修改 LvglFontTool生成的myFont.c

主要是添加BIN文件读操作,这函数里也注释了

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);return __g_font_buf;
}

利用LVGL FS系统来做这个操作

修改如下

 static uint8_t __g_font_buf[364];//如bin文件存在SPI FLASH可使用此buffstatic 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);lv_fs_file_t file;lv_fs_res_t result;result = lv_fs_open(&file, "S:/myFont_font18.bin", LV_FS_MODE_RD);if (result != LV_FS_RES_OK)return NULL;lv_fs_seek(&file, offset, LV_FS_SEEK_CUR);uint32_t len;lv_fs_read(&file, __g_font_buf, size, &len);lv_fs_close(&file);return __g_font_buf;
}

里面S:/路径对应根目录的BIN文件。

然后main.c主函数里如下写入代码

LV_FONT_DECLARE(myFont_font18)          //外部字库申明,不申明会报错int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
{/*Initialize LittlevGL*/lv_init();lv_port_fs_init();/*Initialize the HAL for LittlevGL*/lv_win32_init(hInstance, SW_SHOWNORMAL, 1024, 600, NULL);/*Output prompt information to the console, you can also use printf() to print directly*/LV_LOG_USER("LVGL initialization completed!");lv_obj_t* obj = lv_btn_create(lv_scr_act());lv_obj_set_size(obj, 300, 300);lv_obj_center(obj);lv_obj_t* label = lv_label_create(obj);lv_obj_set_style_text_font(label, &myFont_font18, 0);lv_label_set_text(label, "外部字体测试");lv_obj_center(label);while(!lv_win32_quit_signal) {/* Periodically call the lv_task handler.* It could be done in a timer interrupt or an OS task too.*/lv_task_handler();usleep(10000);       /*Just to let the system breath*/}return 0;
}

这时候,可以编译运行看看能否显示

如果不能,那就需要修改一下main.c文件的格式为UTF8

我这里是用VSCODE来做的,实际上可以用各种编辑器,notepad  sublime这些

修改原因:LVGL只能支持UTF8格式

选择编码重新打开

运行结果

============================XBF大数组方案=================================

这个方法就简单了,直接生成字库.C文件添加到工程里,main.c里主函数如下

LV_FONT_DECLARE(myFont_font18)int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
{/*Initialize LittlevGL*/lv_init();/*Initialize the HAL for LittlevGL*/lv_win32_init(hInstance, SW_SHOWNORMAL, 1024, 600, NULL);/*Output prompt information to the console, you can also use printf() to print directly*/LV_LOG_USER("LVGL initialization completed!");lv_obj_t* obj = lv_btn_create(lv_scr_act());lv_obj_set_size(obj, 300, 300);lv_obj_center(obj);lv_obj_t* label = lv_label_create(obj);lv_obj_set_style_text_font(label, &myFont_font18, 0);lv_label_set_text(label, "外部字体测试");lv_obj_center(label);while(!lv_win32_quit_signal) {/* Periodically call the lv_task handler.* It could be done in a timer interrupt or an OS task too.*/lv_task_handler();usleep(10000);       /*Just to let the system breath*/}return 0;
}

没有使用文件系统,纯靠代码来存字库。

如果没有显示中文,请再检查文件的编码,一定要是UTF8

LVGL8.2 之 模拟器使用外部中文字体,两种方式相关推荐

  1. win7使用android字体文件,字体在哪个文件夹里 win7怎么安装新字体(两种方式)

    对于系统的字体,我们一般都是作为精简系统的选择,为例节省系统盘的空间,把多余的字体都给处理掉,但是做设计师.编辑等职业因为工作需求,用到的字体会很多,所以就需要安装大量的字体.那么自己到底存放在那个文 ...

  2. 创建安卓模拟器的两种方式及常用Android命令介绍

    创建安卓模拟器有以下两种方式: 1>通过图形界面创建,在Eclipse中单击Windows->Android Virtual Device Manager启动图形界面窗口 2>如果用 ...

  3. Android Studio导入外部资源的三种方式

    在Android Studio打开导入外资源的路径:File->Project Structure- 第一步:选择Dependencies 第二步:选择要添加依赖的modules 第三步:为mo ...

  4. Unity中制作自定义字体的两种方式

    Unity支持自定义图片字体(CustomFont),网上有很多教程,细节不尽相同,当概括起来基本就是两种方式.一是使用BMFont,导出图集和.fnt文件,再使用图集在Unity中设置得到字体.二是 ...

  5. go引入外部依赖的三种方式:go get,go module,vendor目录

    本文转载自golang 引入外部包的三种方式:go get, go module, vendor目录_guoguolifang的博客-CSDN博客_golang 外部包 import  "g ...

  6. hive建立内部表映射hbase_Hive 建外链表到 Hbase(分内部表、外部表两种方式)

    一. Hive 建内部表,链到hbase :特点:Hive drop表后,Hbase 表同步删除 drop table if exists hbase_kimbo_test1; CREATE TABL ...

  7. Android studio中TextView改变字体的两种方式(如仿宋、隶书)

    在Android中系统默认的字体有三种,通过在TextView中加上android:typeface="sans"来改变,而sans就是三种当中的其中的一种,还有两种分别是&quo ...

  8. ttc文件linux安装,centos系统安装中文字体几种方法

    前天有用户反应,生成的报到单中他的名字少了一个字.仔细检查了一下,原来是centos系统的默认字体没有他名字中的那个字,于是就直接被忽略了. 其实那个字并不生僻,于是不得不安装中文字体,安装过程也很简 ...

  9. centos系统安装中文字体几种方法

    我们知道centos是基于linux内核的这款系统默认是不带中文字体了,如果我们要使用中文字体就需要自行安装了,下面一起来看看吧. 前天有用户反应,生成的报到单中他的名字少了一个字.仔细检查了一下,原 ...

最新文章

  1. 剑指offer_第7题_斐波那契数列
  2. 一文读懂工业物联网 全面起底核心玩家和技术体系
  3. matplotlib模块学习
  4. P3384 【模板】树链剖分
  5. RabbitMQ—重复消费、数据丢失和消息顺序性
  6. JS----JavaScript中数组扁平化
  7. 【年度回忆录】如何做到1年90000粉丝?
  8. 微软全新Chromium版Edge浏览器下载
  9. android 视频编码vfr cfr,[转载]VFR的源转换CRF输出 批处理
  10. 基于Huffman树的CBOW模型的理解
  11. [转载]:C# 中结构与类的区别
  12. 织梦系统MySQL安装_如何更改已安装的织梦dedecms系统数据库表前缀?
  13. DNS迭代查询与递归查询的区别
  14. element tree不刷新视图_架构蓝图软件架构 quot;4+1quot; 视图模型
  15. java学生管理系统设计_基于JAVA学生管理系统设计和实现.ppt
  16. 计算机怎么安错误,电脑安装软件时提示安装过程出错系统设置未被修改怎么办...
  17. 清华conda源下不了torch_使用清华镜像源安装Pytorch
  18. Chrome下载文件,文件名出现乱码解决
  19. oracle报1653解决办法,“IMP-00058: 遇到 ORACLE 错误 1653”,如何解决?
  20. Nginx动静分离经典配置

热门文章

  1. CRM销售管理系统能够给企业带来哪些好处?
  2. java ssm 基于springboot的志愿者招募网站
  3. mysql 字符集 性能_MySQL字符集不一致导致性能下降25%,你敢信?
  4. TP5中 save操作 不能foreach循环操作 循环就只有最后一次有效 解决方案
  5. 2345看图王2345Pic10.4.0.9254_x64官方净化版
  6. 三洋服务器显示F6,格力空调故障代码f6什么原因
  7. 【历史上的今天】2 月 2 日:公钥密码学发明者诞生;苹果的衰落期;测谎仪首次被使用
  8. 题目标题: 高斯日记
  9. hipaa_构建符合HIPAA的服务。
  10. 等价关系运算c语言大作业,离散数学C语言上机题.doc