你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱STemWin教程】第22章 TrueType矢量字体

[复制链接]
baiyongbin2009 发布时间:2015-1-31 11:26
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第22章 TrueType矢量字体

    本期教程跟大家讲解矢量字体的相关知识,矢量字体最大的好处就是可以任意放大或者缩小字体,而且字体的显示效果不失真。矢量字体的缺点就是不适合用在小型嵌入式系统中,极其消耗内存。
    22. 1  XBF格式字体生成方法
    22. 2 移植到开发板显示
    22. 3 总结
22.1 矢量字体介绍
    下面的内容来自百度百科和wiki百科(两个内容居然一模一样),讲的非常好,特此转载过来。
    目前主流的矢量字体格式有3种:Type1,TrueType和OpenType,这三种格式都是与平台无关的。
    Type1全称PostScript Type1,是1985年由Adobe公司提出的一套矢量字体标准,由于这个标准是基于PostScript Description Language(PDL),而PDL又是高端打印机首选的打印描述语言,所以Type1迅速流行起来。但是Type1是非开放字体,Adobe对使用Type1的公司征收高额的使用费。
    TrueType是1991年由Apple公司与Microsoft公司联合提出另一套矢量字标准。
    Type1使用三次贝塞尔曲线来描述字形,TrueType则使用二次贝塞尔曲线来描述字形。所以Type1的字体比TrueType字体更加精确美观。一个误解是,Type1字体比TrueType字体占用空间多。这是因为同样描述一个圆形,二次贝塞尔曲线只需要8个关键点和7段二次曲线;而三次贝塞尔曲线则需要12个关键点和11段三次曲线。然而实际情况是一般来说 Type1比TrueType要小10%左右。这是因为对于稍微复杂的字形,为了保持平滑,TrueType必须使用更多的关键点。由于现代大部分打印机都是使用PDL作为打印描述语言,所以Type1字体打印的时候不会产生形变,速度快;而TrueType则需要翻译成PDL,由于曲线方程的变化,还会产生一定的形变,不如Type1美观。
    这么说来,Type1应该比TrueType更具有优势,为什么如今的计算机上TrueType反而比Type1使用更广泛呢?这是因为第一:Type1由于字体方程的复杂,所以在屏幕上渲染的时候,花费的时间多,解决方案是大部分Type1字体嵌入了点阵字体,这样渲染快,但是边缘不光滑,比较难看。很多ps文档和ps转换的pdf文档都是这样,在计算机上浏览的时候字体很难看,但是打印出来很美观。TrueType则渲染比较快,可以平滑的显示在屏幕上,看上去很美观。
    第二个原因是Type1的高额使用费,使得Type1没有被所有的操作系统所支持。Windows家族只有OS/2和windows 2000及之后的版本从操作系统级别开始支持Type1。由于这个问题,Adobe只好在其所有的产品中嵌入Adobe Type Manager(ATM)作为渲染引擎。
    OpenType则是Type1与TrueType之争的最终产物。1995年,Adobe公司和Microsoft公司开始联手开发一种兼容Type1和TrueType,并且真正支持Unicode的字体,后来在发布的时候,正式命名为OpenType。OpenType可以嵌入Type1和TrueType,这样就兼有了二者的特点,无论是在屏幕上察看还是打印,质量都非常优秀。可以说OpenType是一个三赢的结局,无论是Adobe、Microsoft还是最终用户,都从OpenType中得到了好处。Windows家族从Windows 2000开始,正式支持OpenType。打开系统的字体目录(一般是C:\Windows\Fonts\或C:\Winnt\Fonts),可以看到:一个红色A的图标的是点阵字体,两个重叠的T的图标是TrueType字体,一个O的图标就是OpenType字体。
    矢量字体扩展名ttf。点阵字体的扩展名是fon.
    下面是XP系统中字体的部分截图:
22.1.png
22.2 STemWin对矢量字体的支持
    TrueType为字体开发人员提供对在各种字体高度下字体显示方式的高度控制。与位图字体(基于每个字符的位图)不同,TrueType字体基于矢量图形。矢量表示的优势在于无损的可扩展性。这意味着,每个字符在绘制前需要光栅化为位图。为避免每次绘制字符时都进行光栅化,通常用字体引擎缓存位图数据。这要求CPU速度快、RAM足够。发货时不含emWin TTF包。该项内容可在www.segger.com/link/emwin_freetype.zip下免费获得。
    emWin对TTF支持的实施基于来自David Turner、Robert Wilhelm和Werner Lembergr的FreeType字体库,该库可在www.freetype.org下免费获得。emWin对该库的使用符合GUI\TrueType\FTL. txt下的FreeType许可。emWin对该库进行了少许改编,添加了带有GUI函数的 “粘贴”层。
    TrueType矢量字体的硬件要求如下:
CPU
TTF支持仅适用于32位CPU。我们对32位CPU的定义为:sizeof(int)= 4。
ROM
TTF引擎的ROM要求大约为250 K。确切大小取决于CPU、编译器以及编译器的优化水平。
RAM
该库的RAM要求主要取决于使用的字体。TTF引擎的基本RAM要求大约为50 K。在使用GUI_TTF_CreateFont()创建GUI字体时,字体引擎会加载生成字符所需的TTF文件中定义的所有字体表。不同字体之间的表大小有所差异。创建字体额外要求的RAM量可能介于几个KB到1 MB以上之间。一般字体需要80-300 kb。取决于使用的字体文件需要多少RAM。至少,TTF引擎需要位图缓存。默认情况下,引擎使用200 K的缓存。足够大多数应用使用。TTF引擎通过非emWin函数malloc()和free()分配内存。使用TTF引擎之前,必须确保
能够运行这些函数。
    从SEGGER官网下载的矢量库主要有以下文件:
22.2.png
    TrueType相关的文件还是很多的,这里只贴了部分源码。
22.3 模拟器上面运行矢量字体
    在emWin模拟器中,官方专门做了一个例子用于运行矢量字体,程序DEMO位置如下:
22.3.png
这个DEMO程序的代码如下:
  1. #ifndef SKIP_TEST

  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include "GUI.h"

  5. /*********************************************************************
  6. *
  7. *       Static data
  8. *
  9. **********************************************************************
  10. */
  11. static unsigned     _aHeight  [] = {16, 20, 32, 48};   // Array of heights used to show text
  12. static GUI_TTF_CS   _aCS      [GUI_COUNTOF(_aHeight)]; // Each GUI font needs its own GUI_TTF_CS structure
  13. static GUI_FONT     _aFont    [GUI_COUNTOF(_aHeight)]; // Array of GUI fonts
  14. static char         _acFamily [200];
  15. static char         _acStyle  [200];

  16. /*********************************************************************
  17. *
  18. *       Static code
  19. *
  20. **********************************************************************
  21. */
  22. /*********************************************************************
  23. *
  24. *       _ShowText
  25. */
  26. static void _ShowText(void) {(1)
  27.   int i;

  28.   GUI_Clear();
  29.   i = 0;
  30.   GUI_TTF_GetFamilyName(&_aFont[i], _acFamily, sizeof(_acFamily));(2)
  31.   GUI_TTF_GetStyleName(&_aFont[i],  _acStyle,  sizeof(_acStyle));
  32.   GUI_SetFont(&GUI_Font20_1);
  33.   GUI_DispString(_acFamily);
  34.   GUI_DispString(", ");
  35.   GUI_DispString(_acStyle);
  36.   GUI_DispNextLine();
  37.   GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
  38.   GUI_SetFont(&_aFont[i]);
  39.   GUI_DispString("abcdefghijklmnopqrstuvwxyz\n");
  40.   GUI_DispString("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
  41.   GUI_DispString("123456789.:,;(:*!?')\n");
  42.   GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
  43.   for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {
  44.     GUI_SetFont(&_aFont[i]);
  45.     GUI_DispString("The quick brown fox jumps over the lazy dog. 1234567890\n");
  46.   }
  47.   GUI_Delay(1000);
  48. }

  49. /*********************************************************************
  50. *
  51. *       _CreateFonts
  52. */
  53. static int _CreateFonts(const U8 * pData, U32 NumBytes) {(3)
  54.   int i;
  55.   GUI_TTF_DATA TTF_Data;        // Only one GUI_TTF_DATA structure is used per font face

  56.   TTF_Data.pData    = pData;    // Set pointer to file data
  57.   TTF_Data.NumBytes = NumBytes; // Set size of file
  58.   for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {
  59.     //
  60.     // Initialize GUI_TTF_CS members
  61.     //
  62.     _aCS[i].PixelHeight = _aHeight[i];
  63.     _aCS[i].pTTF        = &TTF_Data;
  64.     //
  65.     // Create GUI font
  66.     //
  67.     if (GUI_TTF_CreateFont(&_aFont[i], &_aCS[i])) {(4)
  68.       return 1;
  69.     }
  70.   }
  71.   return 0;
  72. }

  73. /*********************************************************************
  74. *
  75. *       _cbFontDemo
  76. *
  77. * Function description
  78. *   The function uses the given pointer to a true type font for creating
  79. *   a couple of GUI fonts and showing the outline of the TTF font.
  80. *
  81. * Parameters:
  82. *   pData    - Location of font file
  83. *   NumBytes - Size of font file
  84. */
  85. static void _cbFontDemo(const U8 * pData, U32 NumBytes) {(5)
  86.   _CreateFonts(pData, NumBytes); // Create fonts
  87.   _ShowText();                   // Show some text
  88.   GUI_TTF_DestroyCache();        // Clear the TTF cache
  89. }

  90. /*********************************************************************
  91. *
  92. *       _IterateOverAllFiles
  93. *
  94. * Function description
  95. *   The function iterates over all files of the given folder and the
  96. *   given mask, reads the contents of the file and calls the function
  97. *   pfDoSomething() with location and size of file data.
  98. *   Can be used under Win32 environment only.
  99. */
  100. static void _IterateOverAllFiles(const char * sFolder, const char * sMask, void (* pfDoSomething)(const U8 * pData, U32 NumBytes)) {(6)
  101.   GUI_RECT Rect = {0, 10, 1000, 1000};
  102.   char              acMask[_MAX_PATH];
  103.   char              acFile[_MAX_PATH];
  104.   WIN32_FIND_DATA   Context;
  105.   HANDLE            hFind;
  106.   HANDLE            hFile;
  107.   U8              * pData;
  108.   DWORD             NumBytes;
  109.   DWORD             NumBytesRead;

  110.   sprintf(acMask, "%s\\%s", sFolder, sMask);
  111.   hFind = FindFirstFile(acMask, &Context);
  112.   if (hFind != INVALID_HANDLE_VALUE) {
  113.     do {
  114.       sprintf(acFile, "%s\\%s", sFolder, Context.cFileName);
  115.       hFile = CreateFile(acFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  116.       if (hFile != INVALID_HANDLE_VALUE) {
  117.         NumBytes = GetFileSize(hFile, NULL);
  118.         pData = (U8 *)malloc(NumBytes);
  119.         ReadFile(hFile, pData, NumBytes, &NumBytesRead, NULL);
  120.         pfDoSomething(pData, NumBytes);
  121.         free(pData);
  122.       }
  123.       CloseHandle(hFile);
  124.     } while (FindNextFile(hFind, &Context));
  125.   }
  126. }

  127. /*********************************************************************
  128. *
  129. *       Public code
  130. *
  131. **********************************************************************
  132. */
  133. /*********************************************************************
  134. *
  135. *       MainTask
  136. */
  137. void MainTask(void) {
  138.   char acPath[200];

  139.   GUI_Init();
  140.   //
  141.   // Set colors and text mode
  142.   //
  143.   GUI_SetBkColor(GUI_WHITE);
  144.   GUI_SetColor(GUI_BLACK);
  145.   GUI_SetTextMode(GUI_TM_TRANS);
  146.   //
  147.   // Get windows system directory and extend it with '\Font'(7)
  148.   //
  149.   GetWindowsDirectory(acPath, sizeof(acPath));
  150.   strcat(acPath, "\\Fonts");
  151.   //
  152.   // Iterate over files and call _cbFontDemo for each file
  153.   //
  154.   while (1) {
  155.     _IterateOverAllFiles(acPath, "*.ttf", _cbFontDemo);
  156.   }
  157. }

  158. #endif
复制代码
1. 这个函数用于文本显示。
2. 函数:GUI_TTF_GetFamilyName 将返回字体文件中定义的字体系列名称
    函数:GUI_TTF_GetStyleName  此函数将返回字体文件中定义的样式名称 (粗体、常规等)
3. 用于字体的创建,注意字体的创建方法
4. 用于实现字体创建的函数,函数中两个成员介绍如下:
    GUI_TTF_CS
数据类型
元素
描述
GUI_TTF_DATA *
pTTF
指向包含要使用的字体文件位置和大小的GUI_TTF_DATA结构
PixelHeight
PixelHeight
新字体的像素高度。表示字形 “g”和 “f”之间周围矩形的高度。请注意,这并非两行文本之间的距离。换句话说,GUI_GetFontSizeY()返回的值与此值并不完全相同。
FaceIndex
FaceIndex
有些字体文件可能包含多种字体风格。对于多种风格,此索引指定使用基于零的风格索引来创建字体。通常为0。
    GUI_TTF_DATA
数据类型
元素
描述
const void *
pData
指向可寻址存储器区域中的TTF字体文件。
NumBytes
NumBytes
文件的大小 (字节)。
5. 字体演示主要运行的程序。注意函数GUI_TTF_DestroyCache 用于释放TTF缓存系统分配的所有内存并解除该缓存。
6. 通过这个程序实现电脑系统中矢量字体的轮番显示。
7. 获取电脑系统中字体存储的路径。
实际显示效果如下(这里只贴了一个截图)
22.4.png

收藏 1 评论15 发布时间:2015-1-31 11:26

举报

15个回答
baiyongbin2009 回答时间:2015-1-31 11:27:26
本帖最后由 baiyongbin2009 于 2015-1-31 11:29 编辑

22.4 移植到开发板上显示

22.4.1 第一步:从官网下载矢量库22.4.2 第二步:添加到emWin工程中(MDK)
22.5.png
    添加上后需要再添加相应的工程路径:
22.6.png
22.4.3 第三步:修改Heap的大小
    由于要使用非emWin自带的molloc和free函数,下面是修改的位置和大小:
22.7.png
    这个地方一定得大点,要不字体无法显示。
22.4.4 第四步:主程序
  1. /*
  2. *********************************************************************************************************
  3. *        函 数 名: MainTask
  4. *        功能说明: GUI主函数
  5. *        形 参:无
  6. *        返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void MainTask(void)
  10. {
  11. OS_ERR err;
  12. char *_acBuffer;
  13. GUI_TTF_CS Cs0, Cs1, Cs2, Cs3;
  14. GUI_TTF_DATA Data;
  15. GUI_FONT Font0, Font1, Font2, Font3;
  16. GUI_HMEM hMem;

  17. GUI_Init();
  18. GUI_SetBkColor(GUI_BLACK);
  19. GUI_SetColor(GUI_RED);

  20. /* 申请一块内存空间 并且将其清零 */ (1)
  21. hMem = GUI_ALLOC_AllocZero(1024*1500);
  22. /* 将申请到内存的句柄转换成指针类型 */
  23. _acBuffer = GUI_ALLOC_h2p(hMem);
  24. /* 打开文件 */
  25. OSSchedLock(&err);
  26. result = f_open(&file, "seg.ttf", FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS); (2)
  27. result = f_read(&file, _acBuffer, file.fsize, &bw);
  28. OSSchedUnlock(&err);

  29. /* Set parameters for accessing the font file */
  30. Data.pData = _acBuffer; /* Address */
  31. Data.NumBytes = file.fsize; /* Size */

  32. /* Set creation parameters of first font */
  33. Cs0.pTTF = &Data; /* Use address of GUI_TTF_DATA */
  34. Cs0.PixelHeight = 24; /* Pixel height */(3)
  35. Cs0.FaceIndex = 0; /* Initialize to 0 */
  36. /* Set creation parameters of second font */
  37. Cs1.pTTF = &Data; /* Use address of GUI_TTF_DATA */
  38. Cs1.PixelHeight = 48; /* Pixel height */
  39. Cs1.FaceIndex = 0; /* Initialize to 0 */
  40. /* Set creation parameters of first font */
  41. Cs2.pTTF = &Data; /* Use address of GUI_TTF_DATA */
  42. Cs2.PixelHeight = 96; /* Pixel height */
  43. Cs2.FaceIndex = 0; /* Initialize to 0 */
  44. /* Set creation parameters of second font */
  45. Cs3.pTTF = &Data; /* Use address of GUI_TTF_DATA */
  46. Cs3.PixelHeight = 144; /* Pixel height */
  47. Cs3.FaceIndex = 0; /* Initialize to 0 */
  48. /* Create 4 fonts */
  49. GUI_TTF_CreateFont(&Font0, &Cs0);(4)
  50. GUI_TTF_CreateFont(&Font1, &Cs1);
  51. GUI_TTF_CreateFont(&Font2, &Cs2);
  52. GUI_TTF_CreateFont(&Font3, &Cs3);
  53. /* Draw something using the fonts */
  54. GUI_SetFont(&Font0);
  55. GUI_DispStringAt("ABC1234", 0, 0);
  56. GUI_SetFont(&Font1);
  57. GUI_DispStringAt("ABC1234", 0, 24);
  58. GUI_SetFont(&Font2);
  59. GUI_DispStringAt("ABC1234", 0, 24+48);
  60. GUI_SetFont(&Font3);
  61. GUI_DispStringAt("ABC1234", 0, 24+48+96);
  62. GUI_DispStringAt("ARMFLY", 0, 24+48+96+144);
  63. while(1)
  64. {
  65. GUI_Delay(100);
  66. }

  67. }
复制代码
1. 申请动态内存用于加载字库。
2. 将矢量字体从SD卡中加载到外接SRAM中。
3. 设置矢量字体点阵大小。
4. 创建四种大小的矢量字体。
22.4.5 第五步:矢量字体放到SD卡中
    由于汉字的矢量字体比较大,使用2MB的SRAM空间不够,这里使用从网上下载的米字体做为显示。
22.8.png
    放到SD卡后,在屏上的实际显示效果如下:
22.9.png
     特别注意,如果使用的是800*480分辨率的屏可以完成显示出来,如果是小于这个分辨率的屏只能显示出一部分,大家可以按照上面的设计方法做一个适合自己屏大小的显示。
22.5 总结
    矢量字体就跟大家讲这么多,更多的知识可以研究下源码的实现。关于字体的显示截至到本期教程就算结束了。


时光碎了天 回答时间:2015-1-31 11:51:16
感觉很不错的
20091217083309-1058990770.jpg
MouseCat 回答时间:2015-1-31 12:17:18
强悍啊,收藏了
cxtarm 回答时间:2015-1-31 12:30:12
强悍 弃天帝签名.jpg
数码小叶 回答时间:2015-1-31 12:51:22
谢谢分享,学习学习
数码小叶 回答时间:2015-1-31 12:51:38
谢谢分享,学习学习
党国特派员 回答时间:2015-1-31 14:10:15
下来学习了
beian10 回答时间:2015-2-1 13:35:43
mark0668 回答时间:2015-6-28 23:18:22
谢谢分享,学习学习
12下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版