在emWin中使用矢量图标字体——2020.11

效果图

先上一张效果图

 

使用方法

emWin中图标字体的使用方法其实很简单,因为这种图标是用ttf字库的形式保存的,所以只要硬件平台的RAM空间支持emWin ttf字库的显示,就可以直接用。显示的方法也很简单,直接调用字符串显示函数即可,这里简单说一下使用方法。

获取图标字体

想要显示图标字体,那首先肯定要能获得图标资源,目前我知道的图标字体网站有两个,一个是阿里巴巴矢量图标库,还有一个是Font Awesome

阿里的图标样式是最丰富的,单色彩色都有,还可以下载png、svg和ai格式,相比之下Font Awesome的优点呢,就是非常方便,接近一千个图标只需要下载一个ttf文件。在这里以阿里的图标库举例。

  • 首先,进到阿里巴巴矢量图标库网页,搜索想要使用的图标,然后点击添加入库,这里需要登录账号才能继续操作,外部账号支持github和微博账号;

  •  
  • 把所有想用的图标全部入库以后,点击页面右上角的购物车图标,会弹出一个对话框,我们选择添加至项目,一般第一次使用会提示没有项目,按照提示新建一个就好;

  •  
  • 进入到项目以后,可以在页面看到之前入库的图标,每个图标下面都有一串字符,这个是图标对应的unicode编码,这些图标对应的编码需要记住,因为emWin显示的时候就是输入这串编码来显示的,点击:下载至本地,就可以把这些图标的字体文件下载下来;

  • 下载完成后,打开压缩包,里面有很多种格式的文件,我们只需要ttf格式的字体文件,这样,图标字体的文件就算拿到了。可以看到,7个图标一共才3KB多,非常小。

程序调用

接下来就是程序上加载和使用图标字体,其实加载方法就和emWin加载普通ttf字库的方法完全相同,只是使用方法稍有区别。

我这里以野火STM32H743 Pro开发板的TTF字体显示例程为基础,模拟器上的使用方法是一样的。下面只会演示如何显示图标字体,至于ttf字体相关的内容请参考野火的emwin教程文档,关于emWin模拟器如何显示ttf字体,可以到这篇帖子了解:如何在VS2019的emwin模拟器中显示中文(出处: 野火电子论坛)

  • 首先,在GUIFont_Create.c中只需修改字体文件的存放路径和名称,我这里是放到了SD卡的一个指定目录,如果是模拟器,就直接放到模拟器工程下的文件夹;
/* 图标文件路径 */
static const char FONT_TTF_ADDR[] = { "0:/Font/iconfont.ttf" };
  • 然后这个文件里剩下的所有内容都不需要改,我这里再贴一下字体的创建函数,下面还要用到。FONT_TTF_24到120就是创建的不同大小的图标字体,名字可以自己定义;
/* 存储器初始化标志 */
static uint8_t Storage_Init_Flag = 0;

/* 字库属性结构体 */
GUI_TTF_CS cs0, cs1, cs2, cs3, cs4;

/* 字库数据结构体 */
GUI_TTF_DATA ttf_data;

/* 定义emwin字体 */
GUI_FONT FONT_TTF_24;
GUI_FONT FONT_TTF_48;
GUI_FONT FONT_TTF_72;
GUI_FONT FONT_TTF_96;
GUI_FONT FONT_TTF_120;

/* 字库数据缓冲区 */
char *TTFfont_buffer;
GUI_HMEM hFontMem;

/* 字库存储路径 */
static const char FONT_STORAGE_ROOT_DIR[] = "0:";
static const char FONT_TTF_ADDR[] = "0:/Font/iconfont.ttf";
/* 字库存储在文件系统时需要使用的变量 */
static FIL fnew;					/* file objects */
static FATFS fs;					/* Work area (file system object) for logical drives */
static FRESULT res; 
static UINT br;            		    /* File R/W count */


/**
  * @brief  获取字体数据
  * @note 无
  * @param res_name:要读取的文件名
  * @retval 无
  */
static void FONT_TTF_GetData(const char *res_name)
{
  if (Storage_Init_Flag == 0)
	{
		/* 挂载sd卡文件系统 */
		res = f_mount(&fs,FONT_STORAGE_ROOT_DIR,1);
		Storage_Init_Flag = 1;
	}
  
  /* 打开文件 */
  taskENTER_CRITICAL();
  res = f_open(&fnew , res_name, FA_OPEN_EXISTING | FA_READ);
  taskEXIT_CRITICAL();
  if(res != FR_OK)
	{
		printf("无法找到字库文件\r\n");
		while(1);
	}
  
  /* 申请一块动态内存空间 */
	hFontMem = GUI_ALLOC_AllocZero(fnew.fsize);
	/* 转换动态内存的句柄为指针 */
	TTFfont_buffer = GUI_ALLOC_h2p(hFontMem);
  
  /* 读取内容 */
  taskENTER_CRITICAL();
	res = f_read( &fnew, TTFfont_buffer, fnew.fsize, &br );
  taskEXIT_CRITICAL();
  if(res != FR_OK)
	{
		printf("无法读取字库文件\r\n");
		while(1);
	}
  f_close(&fnew);
  
  /* 配置属性 */
  ttf_data.pData = TTFfont_buffer;
  ttf_data.NumBytes = fnew.fsize;
  
  /* 配置字体参数 */
  cs0.pTTF = &ttf_data;
  cs0.PixelHeight = 24;
  cs0.FaceIndex = 0;
  
  cs1.pTTF = &ttf_data;
  cs1.PixelHeight = 48;
  cs1.FaceIndex = 0;
  
  cs2.pTTF = &ttf_data;
  cs2.PixelHeight = 72;
  cs2.FaceIndex = 0;
  
  cs3.pTTF = &ttf_data;
  cs3.PixelHeight = 96;
  cs3.FaceIndex = 0;
  
  cs4.pTTF = &ttf_data;
  cs4.PixelHeight = 120;
  cs4.FaceIndex = 0;
}

/**
  * @brief  创建TTF字体
  * @note 无
  * @param 无
  * @retval 无
  */
void Create_TTF_Font(void)
{
  /* 获取字体数据 */
  FONT_TTF_GetData(FONT_TTF_ADDR);

  /* 创建TTF字体 */
  GUI_TTF_CreateFontAA(&FONT_TTF_24,
                       &cs0);
  GUI_TTF_CreateFontAA(&FONT_TTF_48,
                       &cs1);
  GUI_TTF_CreateFontAA(&FONT_TTF_72,
                       &cs2);
  GUI_TTF_CreateFontAA(&FONT_TTF_96,
                       &cs3);
  GUI_TTF_CreateFontAA(&FONT_TTF_120,
                       &cs4);
}
  • 路径改好之后,新建一个icon_unicode.c文件,把之前在网页上的那些图标对应的编码全部用数组存起来,编码前面的"&#x"要换成"\x",不过实际测试中发现在keil5里"\x"只支持2位16进制数,所以只能把"&#x"改成"\u",就像下面这样。
/* 图标编码数组 */
const char *icon_unicode[] = {
  "\ue629",  /* 电池 */
  "\ue62f",  /* 返回 */
  "\ue60d",  /* 蓝牙 */
  "\ue609",  /* wifi */
  "\uec50",  /* USB */
  "\ue680",  /* SD卡 */
  "\ue6bf",  /* 文件夹 */
};

注意:此文件的字符编码格式必须是UTF-8-BOM,否则emWin不会有任何显示。keil5中的设置方法请参考野火的emWin教程文档,模拟器上的设置方法请参考如何在VS2019的emwin模拟器中显示中文,这里不做说明。

icon_unicode.c创建好后,添加到keil5工程中,然后在MainTask.c里定义一个枚举,方便调用图标编码。最后,在MainTask函数里调用GUI_DispStringAt就可以显示图标字体了。

extern const char *icon_unicode[];

enum icon_name{
  BATTERY = 0U, /* 电池 */
  BACK,         /* 返回 */
  BLE,          /* 蓝牙 */
  WIFI,         /* wifi */
  USB,          /* USB */
  SD_CARD,      /* SD卡 */
  FOLDER,       /* 文件夹 */
};

/**
  * @brief GUI主任务
  * @note 无
  * @param 无
  * @retval 无
  */
void MainTask(void)
{
  /* 启用UTF-8编码 */
  GUI_UC_SetEncodeUTF8();
  /* 创建图标字体 */
  Create_TTF_Font();
  
  /* 设置背景颜色 */
  GUI_SetBkColor(GUI_BLUE);
  GUI_Clear();

  /* 设置字体模式和颜色 */
  GUI_SetTextMode(GUI_TM_TRANS);
  GUI_SetColor(GUI_WHITE);

  /* 显示图标 */
  GUI_SetFont(&FONT_TTF_24);
  GUI_DispStringAt(icon_unicode[BATTERY], 24 * 0, 0);
  GUI_DispStringAt(icon_unicode[BACK], 24 * 1, 0);
  GUI_DispStringAt(icon_unicode[BLE], 24 * 2, 0);
  GUI_DispStringAt(icon_unicode[WIFI], 24 * 3, 0);
  GUI_DispStringAt(icon_unicode[USB], 24 * 4, 0);
  GUI_DispStringAt(icon_unicode[SD_CARD], 24 * 5, 0);
  GUI_DispStringAt(icon_unicode[FOLDER], 24 * 6, 0);

  GUI_SetFont(&FONT_TTF_48);
  GUI_DispStringAt(icon_unicode[BATTERY], 48 * 0, 24);
  GUI_DispStringAt(icon_unicode[BACK], 48 * 1, 24);
  GUI_DispStringAt(icon_unicode[BLE], 48 * 2, 24);
  GUI_DispStringAt(icon_unicode[WIFI], 48 * 3, 24);
  GUI_DispStringAt(icon_unicode[USB], 48 * 4, 24);
  GUI_DispStringAt(icon_unicode[SD_CARD], 48 * 5, 24);
  GUI_DispStringAt(icon_unicode[FOLDER], 48 * 6, 24);

  GUI_SetFont(&FONT_TTF_72);
  GUI_DispStringAt(icon_unicode[BATTERY], 72 * 0, 24 + 48);
  GUI_DispStringAt(icon_unicode[BACK], 72 * 1, 24 + 48);
  GUI_DispStringAt(icon_unicode[BLE], 72 * 2, 24 + 48);
  GUI_DispStringAt(icon_unicode[WIFI], 72 * 3, 24 + 48);
  GUI_DispStringAt(icon_unicode[USB], 72 * 4, 24 + 48);
  GUI_DispStringAt(icon_unicode[SD_CARD], 72 * 5, 24 + 48);
  GUI_DispStringAt(icon_unicode[FOLDER], 72 * 6, 24 + 48);

  GUI_SetFont(&FONT_TTF_96);
  GUI_DispStringAt(icon_unicode[BATTERY], 96 * 0, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[BACK], 96 * 1, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[BLE], 96 * 2, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[WIFI], 96 * 3, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[USB], 96 * 4, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[SD_CARD], 96 * 5, 24 + 48 + 72);
  GUI_DispStringAt(icon_unicode[FOLDER], 96 * 6, 24 + 48 + 72);

  GUI_SetFont(&FONT_TTF_120);
  GUI_DispStringAt(icon_unicode[BATTERY], 120 * 0, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[BACK], 120 * 1, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[BLE], 120 * 2, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[WIFI], 120 * 3, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[USB], 120 * 4, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[SD_CARD], 120 * 5, 24 + 48 + 72 + 96);
  GUI_DispStringAt(icon_unicode[FOLDER], 120 * 6, 24 + 48 + 72 + 96);
  
  while(1)
  {
    GUI_Delay(10);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值