硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6497|回复: 11
收起左侧

[emWin教程入门篇] 【STemWin教程】第20章 XBF外置字体方法(官方推荐)

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2015-1-28 16:19:26 | 显示全部楼层 |阅读模式
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第20章 XBF外置字体方法(官方推荐)

    官方给的这种外置字体方法非常好,而且还可以支持抗锯齿,显示效果非常好,本期教程就是教会大家这种方式。用FontCvt生成的XBF格式字体文件可以在外部存储器,本期教程就以SD卡为例跟大家讲解。
    20. 1  XBF格式字体生成方法
    20. 2 移植到开发板上显示
    20. 3 总结
20.1 XBF格式字体生成方法
    这里我们使用FontCvt生成一种微软雅黑字体,字体选择36号并选带扩展的4位抗锯齿效果。

20.1.1 第一步:选择带扩展的4位抗锯齿

20.1.png


20.1.2 第二步:选择字体类型和大小

20.2.png

20.1.3 第三步:另存为XBF格式文件

20.3.png
20.4.png

此过程字体生成的时间有点长,大家要耐心等待,生成后文件大小:
20.5.png


20.2 移植到开发板上显示
    移植到开发上的程序主要分为两部分,一个是从SD卡中读取字体的驱动,另一个建立一个对话框显示字体。

20.2.1 创建XBF字体

  1. GUI_XBF_DATA XBF_Data;
  2. GUI_FONT     XBF_Font;
  3. FIL          Fontfile;
  4. /*
  5. *********************************************************************************************************
  6. *
  7. *       _cbGetData
  8. *
  9. * Function description
  10. *   Callback function for getting font data
  11. *
  12. * Parameters:
  13. *   Off      - Position of XBF file to be read
  14. *   NumBytes - Number of requested bytes
  15. *   pVoid    - Application defined pointer
  16. *   pBuffer  - Pointer to buffer to be filled by the function
  17. *
  18. * Return value:
  19. *   0 on success, 1 on error
  20. *********************************************************************************************************
  21. */
  22. static int _cbGetData(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer) (1)
  23. {
  24. FIL *FontFile;
  25. /* The pVoid pointer may be used to get a file handle */
  26. FontFile = (FIL *)pVoid;
  27. /*
  28. * Set file pointer to the required position
  29. */
  30. result =f_lseek(FontFile, Off);
  31. if (result != FR_OK)
  32. {
  33. return 1; /* Error */
  34. }
  35. /*
  36. * Read data into buffer
  37. */
  38. result = f_read(FontFile, pBuffer, NumBytes, &bw);
  39. if (result != FR_OK)
  40. {
  41. return 1; /* Error */
  42. }
  43. return 0;
  44. }
  45. /*
  46. *********************************************************************************************************
  47. *    函 数 名: _ShowXBF
  48. *    功能说明: 使用XBF字体
  49. *    形    参:无
  50. *    返 回 值: 无
  51. *********************************************************************************************************
  52. */
  53. static void _ShowXBF(void)
  54. {
  55. result = f_open(&Fontfile, "YaHe.xbf", FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);(2)
  56. if (result != FR_OK)
  57. {
  58. return;
  59. }
  60. //
  61. // Create XBF font
  62. //
  63. GUI_XBF_CreateFont(&XBF_Font,       // Pointer to GUI_FONT structure in RAM(3)
  64. &XBF_Data,         // Pointer to GUI_XBF_DATA structure in RAM
  65. GUI_XBF_TYPE_PROP_AA4_EXT, // Font type to be created
  66. _cbGetData,        // Pointer to callback function
  67. &Fontfile);        // Pointer to be passed to GetData function
  68. }
复制代码
1. 从SD卡中读取字体文件的方法。
2. 由于没有开启FatFS的长文件名,文件的名字要符合8.3格式。
3. 创建XBF_Font字体。默认情况下,每个字符的数据字节最大值限制为200。这应该满足大部分要求。如果加载使用更多字节的字符,在调试版本中将生成警告。通过向文件GUIConf.h添加以下定义可增加默认值:
    #define GUI_MAX_XBF_BYTES 500 // Sets the maximum number of bytes/chars to 500
    默认的定义在文件GUI_ConfDefaults.h文件里面:
    #ifndef   GUI_MAX_XBF_BYTES
     #define GUI_MAX_XBF_BYTES 200
    #endif

20.2.2 主函数
  1. /*
  2. *********************************************************************************************************
  3. *    对话框信息
  4. *********************************************************************************************************
  5. */
  6. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  7.     { FRAMEWIN_CreateIndirect,  "armfly",            0,                       0,  0,  800,480,FRAMEWIN_CF_MOVEABLE,0},
  8.     { BUTTON_CreateIndirect,    "安富莱电子",        GUI_ID_BUTTON0,          390,40,360,100,0,0},
  9.     { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT0,            5, 10, 300, 70, 0,0},
  10.     { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT1,            5, 80,300, 70, 0,0},
  11.     { TEXT_CreateIndirect,      "安富莱电子",        GUI_ID_TEXT2,            5, 160,300, 70, 0,0}
  12. };
  13. /*
  14. *********************************************************************************************************
  15. *    函 数 名: PaintDialog
  16. *    功能说明: 重绘函数
  17. *    形    参:pMsg 消息指针
  18. *    返 回 值: 无
  19. *********************************************************************************************************
  20. */
  21. void PaintDialog(WM_MESSAGE * pMsg)
  22. {
  23.     WM_HWIN hWin = pMsg->hWin;
  24. }
  25. /*
  26. *********************************************************************************************************
  27. *    函 数 名: InitDialog
  28. *    功能说明: 对话框初始化
  29. *    形    参:pMsg 消息指针
  30. *    返 回 值: 无
  31. *********************************************************************************************************
  32. */
  33. void InitDialog(WM_MESSAGE * pMsg)
  34. {
  35.     WM_HWIN hWin = pMsg->hWin;
  36.     //
  37.     //FRAMEWIN
  38.     //
  39.     FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII);
  40.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  41.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  42.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  43.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  44.     FRAMEWIN_SetTitleHeight(hWin,35);
  45.     //
  46.     //GUI_ID_BUTTON0
  47.     //
  48. _ShowXBF();(1)
  49. GUI_UC_SetEncodeUTF8();(2)
  50.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&XBF_Font);(3)
  51.     //
  52.     //GUI_ID_TEXT0
  53.     //
  54. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
  55.     TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&XBF_Font);
  56. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN);
  57. TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&XBF_Font);
  58. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  59. TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&XBF_Font);
  60. //     GUI_UC_SetEncodeNone();
  61. }
  62. /*
  63. *********************************************************************************************************
  64. *    函 数 名: _cbCallback
  65. *    功能说明: 对话框回调函数
  66. *    形    参:无
  67. *    返 回 值: 无
  68. *********************************************************************************************************
  69. */
  70. static void _cbCallback(WM_MESSAGE * pMsg)
  71. {
  72.     int NCode, Id;
  73.     WM_HWIN hWin = pMsg->hWin;
  74.     switch (pMsg->MsgId)
  75.     {
  76.         case WM_PAINT:
  77.             PaintDialog(pMsg);
  78.             break;
  79.         case WM_INIT_DIALOG:
  80.             InitDialog(pMsg);
  81.             break;
  82.         case WM_KEY:
  83.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  84.             {
  85.                 case GUI_KEY_ESCAPE:
  86.                     GUI_EndDialog(hWin, 1);
  87.                     break;
  88.                 case GUI_KEY_ENTER:
  89.                     GUI_EndDialog(hWin, 0);
  90.                     break;
  91.             }
  92.             break;
  93.         case WM_NOTIFY_PARENT:
  94.             Id = WM_GetId(pMsg->hWinSrc);
  95.             NCode = pMsg->Data.v;        
  96.             switch (Id)
  97.             {
  98.                 case GUI_ID_OK:
  99.                     if(NCode==WM_NOTIFICATION_RELEASED)
  100.                         GUI_EndDialog(hWin, 0);
  101.                     break;
  102.                 case GUI_ID_CANCEL:
  103.                     if(NCode==WM_NOTIFICATION_RELEASED)
  104.                         GUI_EndDialog(hWin, 0);
  105.                     break;
  106.             }
  107.             break;
  108.         default:
  109.             WM_DefaultProc(pMsg);
  110.     }
  111. }
  112. /*
  113. *********************************************************************************************************
  114. *    函 数 名: MainTask
  115. *    功能说明: GUI主函数
  116. *    形    参:无
  117. *    返 回 值: 无
  118. *********************************************************************************************************
  119. */
  120. void MainTask(void)
  121. {
  122.     GUI_Init();
  123.     WM_SetDesktopColor(GUI_WHITE);       /* Automacally update desktop window */
  124.     WM_SetCreateFlags(WM_CF_MEMDEV);     /* Use memory devices on all windows to avoid flicker */
  125. PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  126. FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);
  127. PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  128. BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);
  129. CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);
  130. DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);
  131. SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);
  132. SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);
  133. HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);
  134. RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);
  135.     GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  136. while(1)
  137. {
  138. GUI_Delay(10);
  139. }
  140. }
复制代码
1. 创建XBF字体。
2. 使能UTF-8解码
3. 在按钮中显示的字体使用XBF字体。
4. 还有最重要的一条,上面的这些函数都是在MainTask.c文件里面的,这个文件的编码格式必须得是UTF-8,设置方法在前面18.1.6小节有说明。
实际显示效果如下:
20.6.png

    特别注意,如果使用的是800*480分辨率的屏可以完成显示出来,如果是小于这个分辨率的屏只能显示出一部分,大家可以按照上面的设计方法做一个适合自己屏大小的显示或者直接拖动这个对话框即可。

20.3 总结
    推荐大家在以后的工程中采用这种方式,这种显示方式有个问题就是显示速度有点慢。比如本期教程显示微软雅黑36号字体,4位抗锯齿。显示就有缓慢,显示小字体不带抗锯齿还是没问题的。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

6

主题

32

回帖

6

积分

新手上路

积分
6
发表于 2015-1-29 10:15:44 | 显示全部楼层
这种方式占用FLASH 太大了,推荐  csv 的方式
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107549
QQ
发表于 2015-1-29 10:42:31 | 显示全部楼层

回 true_casey 的帖子

true_casey:这种方式占用FLASH 太大了,推荐  csv 的方式 (2015-01-29 10:15) 
这个是外置的,不占用内部flash。
回复

使用道具 举报

6

主题

32

回帖

6

积分

新手上路

积分
6
发表于 2015-2-2 16:53:18 | 显示全部楼层
外置的FLASH 也有有容量限制的, 我们设备外部FLASH 最大2M,多个语言几乎吃不消
回复

使用道具 举报

6

主题

32

回帖

6

积分

新手上路

积分
6
发表于 2015-2-2 16:55:58 | 显示全部楼层
对了,我用的最新的526,要是能提供一个 用户级的写字符像素点函数就好了,那样,所有的字都是标准的单色图片,然后我们稍微做一点操作就可以了,这样的好处是,所有的字串,都是单色图片,这样省掉大半的FLASH
我记得看到别人帖子说 516之前是可以的,不知道526 有没有
回复

使用道具 举报

336

主题

2045

回帖

3058

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3058
发表于 2015-2-2 17:10:24 | 显示全部楼层

回 true_casey 的帖子

true_casey:对了,我用的最新的526,要是能提供一个 用户级的写字符像素点函数就好了,那样,所有的字都是标准的单色图片,然后我们稍微做一点操作就可以了,这样的好处是,所有的字串,都是单色图片,这样省掉大半的FLASH
我记得看到别人帖子说 516之前是可以的,不知道526 有没有 (2015-02-02 16:55) 
或许直接调用: _SetPixelIndex()
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107549
QQ
发表于 2015-2-2 21:03:49 | 显示全部楼层

回 true_casey 的帖子

true_casey:对了,我用的最新的526,要是能提供一个 用户级的写字符像素点函数就好了,那样,所有的字都是标准的单色图片,然后我们稍微做一点操作就可以了,这样的好处是,所有的字串,都是单色图片,这样省掉大半的FLASH
我记得看到别人帖子说 516之前是可以的,不知道526 有没有 (2015-02-02 16:55) 
使用但图片不方便,还是XBF或者SIF字体方便,很好用。
回复

使用道具 举报

9

主题

19

回帖

46

积分

新手上路

积分
46
发表于 2015-7-31 16:23:46 | 显示全部楼层
我按照这个教程做了,可是显示出来的都是乱码,UTF8我开不开都不行,
QQ图片20150731161837.jpg
QQ图片20150731162142.jpg
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107549
QQ
发表于 2015-7-31 18:29:44 | 显示全部楼层

回 chenyongand 的帖子

chenyongand:我按照这个教程做了,可是显示出来的都是乱码,UTF8我开不开都不行,

 (2015-07-31 16:23) 
记得设置你贴出来的函数所在C文件设置为UTF-8格式。
回复

使用道具 举报

2

主题

16

回帖

2

积分

新手上路

积分
2
发表于 2016-6-28 15:59:36 | 显示全部楼层
我直接移植了第20期的例程,但是改为了不带UCOS的,SD读写各方面都正常,就是在初始化对话框的时候调用到定义的GUI字体是会进入
硬件中断错误,
GUI_UC_SetEncodeUTF8();
    BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&XBF_Font);
   
    //
    //GUI_ID_TEXT0
    //
    TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
//TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&XBF_Font);
    TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN);
    //TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&XBF_Font);
    TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
    //TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&XBF_Font);
注释掉就不会运行就不会有错误,
这是什么原因啊?
回复

使用道具 举报

2

主题

16

回帖

2

积分

新手上路

积分
2
发表于 2016-6-28 16:35:02 | 显示全部楼层
刚刚出现错误的原因是YaHe.xbf文件里面是空的,现在遇到一个新问题,
字体没有显示出来对话框建立和按键可以显示
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107549
QQ
发表于 2016-7-1 07:18:12 | 显示全部楼层

回 zhangjie 的帖子

zhangjie:刚刚出现错误的原因是YaHe.xbf文件里面是空的,现在遇到一个新问题,
字体没有显示出来对话框建立和按键可以显示 (2016-06-28 16:35) 
估计是你的UTF-8编码没有设置。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-5 14:09 , Processed in 0.204932 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表