特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
$ V: v5 l1 P" ?3 w% |1 m6 {第22章 TrueType矢量字体 2 U# Y* Q- I& n7 I$ G4 r4 Q
本期教程跟大家讲解矢量字体的相关知识,矢量字体最大的好处就是可以任意放大或者缩小字体,而且字体的显示效果不失真。矢量字体的缺点就是不适合用在小型嵌入式系统中,极其消耗内存。 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.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矢量字体的硬件要求如下: | TTF支持仅适用于32位CPU。我们对32位CPU的定义为:sizeof(int)= 4。 | | TTF引擎的ROM要求大约为250 K。确切大小取决于CPU、编译器以及编译器的优化水平。 | | 该库的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官网下载的矢量库主要有以下文件: TrueType相关的文件还是很多的,这里只贴了部分源码。 22.3 模拟器上面运行矢量字体 在emWin模拟器中,官方专门做了一个例子用于运行矢量字体,程序DEMO位置如下: 这个DEMO程序的代码如下: - #ifndef SKIP_TEST
! ^+ I) W; Q& S" A, K- h -
; b' X; e. c/ r6 r - #include <windows.h>
/ D0 z6 @, f1 ^$ d% a! O& w - #include <stdio.h>0 ]4 ~2 h% R M# z# K" S
- #include "GUI.h"
( l0 ]/ {) }3 }9 A3 c/ l -
$ h7 |0 w2 N% t - /*********************************************************************2 D D) J/ _7 T. Y- P% ~
- *
2 C" ^% _1 J: M, c3 v* G - * Static data
9 ?6 `- B4 q2 e - *
- G) c2 C3 `. k - **********************************************************************+ n. \9 U( z# X0 x8 h+ J# K I
- */
+ x6 }$ ^5 ?! Y) h M - static unsigned _aHeight [] = {16, 20, 32, 48}; // Array of heights used to show text
5 R) v; Q4 ~( E# F - static GUI_TTF_CS _aCS [GUI_COUNTOF(_aHeight)]; // Each GUI font needs its own GUI_TTF_CS structure4 M" t5 K3 O3 n3 f9 w; ]
- static GUI_FONT _aFont [GUI_COUNTOF(_aHeight)]; // Array of GUI fonts
2 Q- s2 M R% Z0 {8 B - static char _acFamily [200];
& R' z) h. s% m* H) L - static char _acStyle [200];
9 _$ t4 C5 s4 F -
; t! J- @; v7 b - /*********************************************************************+ N4 f2 B3 j5 i' g/ x9 u
- *
! p9 J5 ]3 W8 ] - * Static code/ n1 P. {1 y6 O& S
- *
! j5 n5 `& d* _5 x9 U - **********************************************************************
7 ^0 t& x- ~8 l" [% D - */
9 B7 _' V1 A) I. _5 l$ K3 d2 m1 U8 [ - /*********************************************************************
- b5 d- T. a7 q: ]5 K1 ~( H4 |( f - *
+ h# P" m5 ^8 ]/ F- _ - * _ShowText; }* M4 C# E) K$ E9 L6 Z
- */
- x" I" C. F u, Y1 E - static void _ShowText(void) {(1)- ]: x& m1 _; y4 o9 [
- int i;
# U5 J* \* B% j* B+ G: o -
3 K( m) }/ R/ L - GUI_Clear();
/ x9 U. }2 {. p& Z - i = 0;! ~! M" ?; r5 |& \/ x
- GUI_TTF_GetFamilyName(&_aFont[i], _acFamily, sizeof(_acFamily));(2)) }+ k. k+ ~! g; t# R2 O9 C
- GUI_TTF_GetStyleName(&_aFont[i], _acStyle, sizeof(_acStyle));& ~2 I8 p7 D* L, [
- GUI_SetFont(&GUI_Font20_1);
$ F- U! M3 x- a% C9 z - GUI_DispString(_acFamily);7 m$ l* v+ a+ m6 N: g
- GUI_DispString(", ");
* n1 m" ~: r3 Z. A; U - GUI_DispString(_acStyle);: V3 M. E0 x! I' F; N
- GUI_DispNextLine();7 o1 _& W. y& w6 a( O# _$ D
- GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
8 ]1 b" g L4 b0 q5 n - GUI_SetFont(&_aFont[i]);
2 V! {, {8 r/ Q9 Q/ F3 D - GUI_DispString("abcdefghijklmnopqrstuvwxyz\n");
8 N% a$ W6 o {) d, ` - GUI_DispString("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
* B6 R9 n4 P) g0 b - GUI_DispString("123456789.:,;(:*!?')\n");
6 o) K6 ~0 m1 Y6 _6 `- @ - GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
9 d! j7 `' H; a6 `- U' |( ~$ Y - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {( G1 M2 m9 ?' p5 D" C% w
- GUI_SetFont(&_aFont[i]);
( p; X3 c7 b# T, X8 o, y( |0 s9 v - GUI_DispString("The quick brown fox jumps over the lazy dog. 1234567890\n");
" _- X; F m+ V Z' D, c& m: v1 D - }- v+ [; [* i" j; J( [8 b& U
- GUI_Delay(1000);1 r. S( t" w) S
- }
& j7 U1 \, x. S, n -
, g* i Y% X% k; O - /*********************************************************************
* `3 U' Z" ?& K- X) M7 h - *
% Z9 j: E% L h9 h( ~ P - * _CreateFonts8 I+ N( \5 y& i, _
- */6 A' t9 L4 p3 p% l( y) P
- static int _CreateFonts(const U8 * pData, U32 NumBytes) {(3)
& k$ w) }# L5 ^5 T2 g - int i;
' Q1 ?/ w/ i& ` - GUI_TTF_DATA TTF_Data; // Only one GUI_TTF_DATA structure is used per font face
- }- _6 [& O7 Z- r9 S* h& R; V -
( F# P8 _ S3 u - TTF_Data.pData = pData; // Set pointer to file data# u/ W7 ?4 _+ H4 D1 e0 w
- TTF_Data.NumBytes = NumBytes; // Set size of file
! }: j' Y' D; X+ R. D; F; p9 g - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {. V, O# Q# a# h* i8 g6 ^: t
- //; P$ ^" K& X/ P1 G
- // Initialize GUI_TTF_CS members5 W- S4 `/ q; m+ o% v1 K; s
- //! a2 I5 R5 Q' d+ P
- _aCS[i].PixelHeight = _aHeight[i];
8 t. b8 B* e& [4 v - _aCS[i].pTTF = &TTF_Data;
; U. F) x. O( y) z8 z - //: C7 a( X- R ~; f7 W
- // Create GUI font6 ]( Z. R3 J& h1 J( |. m) D; v! C
- //6 o, g' O( Y s4 U) [0 W1 U
- if (GUI_TTF_CreateFont(&_aFont[i], &_aCS[i])) {(4)6 G, m% D1 y9 z" R1 ^8 Z9 j2 J
- return 1;! o6 Z ?. F& D7 R. ]% p4 K8 ~
- }6 M6 m, {, \2 M
- }
1 |7 P- N5 z" u5 g# ]! Y - return 0;
$ \# t. b. T5 q9 u7 z1 F" P2 W, r - }
" \ w5 b$ F& i) G$ Y1 ?# ^# q - ; o) y) f+ K( _% Y" d
- /*********************************************************************% }1 ?, y" O8 ?5 n, L: R Y- ^
- *5 l, b9 s( `% ?' h/ w8 U! M; \
- * _cbFontDemo5 t: z) r& [7 `1 y) a
- *7 r6 |. e# `0 A
- * Function description( _0 N7 K) m! s$ }
- * The function uses the given pointer to a true type font for creating; U* U/ e4 W) O4 v0 q2 V
- * a couple of GUI fonts and showing the outline of the TTF font.! @, V0 Q% _3 ]# v$ a
- *# I, a$ T# U- C' S( a* A
- * Parameters:4 Z2 T2 C6 Y. ~
- * pData - Location of font file% i* X R) q7 t
- * NumBytes - Size of font file2 W* U7 J8 j% N& ]5 K9 V) ]& \
- */: o7 Y2 R- w r* p- Y5 X& C/ y
- static void _cbFontDemo(const U8 * pData, U32 NumBytes) {(5)
: _, q$ I5 I S+ Z% q( f$ U+ i - _CreateFonts(pData, NumBytes); // Create fonts- ?5 y! k Z/ K8 J
- _ShowText(); // Show some text
\' x. `0 g+ a: Z- K4 t/ F% D! p7 F' K - GUI_TTF_DestroyCache(); // Clear the TTF cache, u' m! X/ F: d: W
- }. y6 I6 D7 H' d$ V% h# u! N
-
$ V! c$ |. L( O, l B4 S. _* i P - /*********************************************************************. |0 P* j' f# c, Z5 {
- *
+ p/ _. x- D& l$ Y- ~& q - * _IterateOverAllFiles! A d% a" u1 J7 Y" u
- * c: ?$ U# v# d k! S& z
- * Function description& r+ G- ?9 Q" i+ j. q) ~7 E# {
- * The function iterates over all files of the given folder and the1 }+ o( _3 }8 L; t0 y) h
- * given mask, reads the contents of the file and calls the function7 y5 v, q6 ^( P$ B* f, A2 }
- * pfDoSomething() with location and size of file data.
6 u# t* {0 ^& g5 @; | Q - * Can be used under Win32 environment only.3 U7 O* Q6 C" j! c0 D
- */
* P4 y$ m! @4 G - static void _IterateOverAllFiles(const char * sFolder, const char * sMask, void (* pfDoSomething)(const U8 * pData, U32 NumBytes)) {(6)' c: _0 k1 r ^' ?% ]
- GUI_RECT Rect = {0, 10, 1000, 1000};
/ R) G5 r0 }+ {* B - char acMask[_MAX_PATH];: O" p C( t0 a+ R- P4 Q
- char acFile[_MAX_PATH];1 R' w+ w, M# @& x4 k: A& y" \
- WIN32_FIND_DATA Context;2 r4 t) {5 c3 a
- HANDLE hFind;
8 g' H b( V1 n/ V& H7 y - HANDLE hFile;" R1 C' x( x V. g/ G
- U8 * pData;
2 h2 x, f% d5 d5 T0 P - DWORD NumBytes;
F) j$ T/ W. u. I- B; g, I - DWORD NumBytesRead;
( k6 D, @* |4 ^+ V4 V -
, H$ M8 Y7 t" ?) B* {% E& Q - sprintf(acMask, "%s\\%s", sFolder, sMask);( `' k+ b5 ^$ [3 ?7 p2 H' @
- hFind = FindFirstFile(acMask, &Context);) o4 o, p! \$ N+ Z
- if (hFind != INVALID_HANDLE_VALUE) {* b! P9 P& @5 y! F
- do {
5 `' ^2 y- S) Q: H& R - sprintf(acFile, "%s\\%s", sFolder, Context.cFileName);' \1 f0 O, w Y. V! o
- hFile = CreateFile(acFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);* ?3 f0 r+ h* ^. l5 `6 x/ O+ W) @
- if (hFile != INVALID_HANDLE_VALUE) {) p% B4 c: [' R) g& T$ J# K
- NumBytes = GetFileSize(hFile, NULL);
; a" C9 M A: W - pData = (U8 *)malloc(NumBytes);4 ^; u' R7 t" x& o2 b F& e
- ReadFile(hFile, pData, NumBytes, &NumBytesRead, NULL);
* G1 M4 }) {0 ?1 d+ ?& e# o# G - pfDoSomething(pData, NumBytes);; _$ ?6 J& T4 c/ l: N4 p0 _8 e
- free(pData);& Y, N' r k3 B! m
- }. L- g# I# w1 c# L* e
- CloseHandle(hFile); e0 [! a( G2 _' @( _6 p; c
- } while (FindNextFile(hFind, &Context));7 i9 ]) d- R( u: e
- }) L0 R: O5 i V6 D8 O( ^
- }
( X# H+ _! F. ~' D - # X3 [9 S' X) [
- /*********************************************************************0 l4 ?2 n( z( R$ }5 l& { M$ g7 ?
- *
- p( e6 w' J4 S2 b! e - * Public code. ]1 J0 _2 s& [
- *
; `; `" ~7 |$ \, @% O& ]7 W - **********************************************************************7 z2 w+ ?" O# v; K: }
- */
( f( u$ g' |7 u, n. c- |! g - /*********************************************************************
& K1 A. m. D. t4 k" B - *; l5 R6 m6 N2 m; `) \% }
- * MainTask! r- u7 A. v5 b. T$ Q; S% y
- */
% `( a! H- R7 g) X7 P. h/ H - void MainTask(void) {' E+ ?& V: Q1 T9 E2 [9 W
- char acPath[200];
5 }1 [9 _, H; Z' s0 S" u - 3 d* a# N1 }$ x1 [; Q
- GUI_Init();
/ s" ~8 T" x3 y9 ]( E. I+ X# ]* V - //
% U' ?# {/ {4 u" i% d - // Set colors and text mode
. N; [5 z9 w9 f+ I - // ?3 b7 t! l; e8 Q/ x
- GUI_SetBkColor(GUI_WHITE);
8 C( E+ N. q; E7 V; Q" k - GUI_SetColor(GUI_BLACK);
/ H1 G: P e N& a& Z - GUI_SetTextMode(GUI_TM_TRANS);
5 \% y* H t$ C, J- [8 N+ B - //9 w# x9 [6 A* z; H% f0 P
- // Get windows system directory and extend it with '\Font'(7)9 |* R7 E; F1 V, t, t/ f# K
- //
) o9 q) g" O* W) Z& Y+ R" m% K! i0 d - GetWindowsDirectory(acPath, sizeof(acPath));8 E+ [" Y, |6 K( w& a
- strcat(acPath, "\\Fonts");" y/ H4 s/ p: Y1 y+ ^
- //, c) q8 y! O* F/ A& V; M9 e& N
- // Iterate over files and call _cbFontDemo for each file: w; s9 V8 |& g p
- //6 `8 X! x5 T( |/ s6 k Q1 l
- while (1) {
0 f$ ~ C8 V9 E+ N# n* ~5 n - _IterateOverAllFiles(acPath, "*.ttf", _cbFontDemo);
" y+ Q4 z7 ^( C: F - }
8 z+ N8 c& M7 g7 I2 O, b - }
7 A% u& c) k) h7 b% [- M -
) a( h) G' ~% w0 g; _1 E$ I1 D' ~ - #endif
复制代码1. 这个函数用于文本显示。 2. 函数:GUI_TTF_GetFamilyName 将返回字体文件中定义的字体系列名称 函数:GUI_TTF_GetStyleName 此函数将返回字体文件中定义的样式名称 (粗体、常规等) 3. 用于字体的创建,注意字体的创建方法 4. 用于实现字体创建的函数,函数中两个成员介绍如下: GUI_TTF_CS | 元素 | | | pTTF | 指向包含要使用的字体文件位置和大小的GUI_TTF_DATA结构 | | PixelHeight | 新字体的像素高度。表示字形 “g”和 “f”之间周围矩形的高度。请注意,这并非两行文本之间的距离。换句话说,GUI_GetFontSizeY()返回的值与此值并不完全相同。 | | FaceIndex | 有些字体文件可能包含多种字体风格。对于多种风格,此索引指定使用基于零的风格索引来创建字体。通常为0。 |
GUI_TTF_DATA 5. 字体演示主要运行的程序。注意函数GUI_TTF_DestroyCache 用于释放TTF缓存系统分配的所有内存并解除该缓存。 6. 通过这个程序实现电脑系统中矢量字体的轮番显示。 7. 获取电脑系统中字体存储的路径。 实际显示效果如下(这里只贴了一个截图) - l# J) |% u% T, H
|
22.4 移植到开发板上显示" L( w* k' `+ ~' W, }# N, b3 V
; j; J7 j9 @4 }; m4 q) H
22.4.1 第一步:从官网下载矢量库