硬汉嵌入式论坛

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

[emWin教程入门篇] 【STemWin教程】第22章 TrueType矢量字体

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2015-1-29 11:01:53 | 显示全部楼层 |阅读模式
特别说明:完整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


22.4 移植到开发板上显示
22.4.1 第一步:从官网下载矢量库
    下载地址:www.segger.com/link/emwin_freetype.zip

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 总结
    矢量字体就跟大家讲这么多,更多的知识可以研究下源码的实现。关于字体的显示截至到本期教程就算结束了。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

45

主题

45

回帖

45

积分

初级会员

积分
45
发表于 2016-3-7 14:51:06 | 显示全部楼层
能转发个米字体矢量字体给我吗/
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107128
QQ
发表于 2016-3-7 14:58:17 | 显示全部楼层

回 pengzisheng 的帖子

pengzisheng:
能转发个米字体矢量字体给我吗/   
seg.rar (9 KB, 下载次数: 94)
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-19 18:17 , Processed in 0.171818 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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