特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接6 f/ |8 H" \6 c- c6 {+ C
第22章 TrueType矢量字体
7 k% _+ b; |- _* H" a0 | 本期教程跟大家讲解矢量字体的相关知识,矢量字体最大的好处就是可以任意放大或者缩小字体,而且字体的显示效果不失真。矢量字体的缺点就是不适合用在小型嵌入式系统中,极其消耗内存。 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; L2 e3 l/ ~0 ~2 w0 _. W
-
9 h- {% {3 n% f8 ^# \ - #include <windows.h>; G# h) E0 n9 G I+ g+ M$ Y
- #include <stdio.h>
3 n3 y9 J6 f8 s0 q& U4 }, w' G - #include "GUI.h"4 J/ }! q0 M% o4 c& N* D. |
-
& A2 O9 e4 N9 u3 i- f3 c! t. W5 {! f - /*********************************************************************$ i: a P( ~1 e/ T) N+ J- G
- *
0 n" n9 H: j6 o3 Z. Q; y, @ - * Static data
. [/ O$ k* K0 e& T) j - *
0 c1 l. ^- U) \# X3 d+ \7 Q - **********************************************************************
' _1 s& `% s0 ~ _. | - */
+ b8 j8 b9 z: t6 z5 ?( Y- N - static unsigned _aHeight [] = {16, 20, 32, 48}; // Array of heights used to show text
: i6 G, W, ^# a; a) W - static GUI_TTF_CS _aCS [GUI_COUNTOF(_aHeight)]; // Each GUI font needs its own GUI_TTF_CS structure
) M8 h$ N0 b6 X) q# I" o0 L F2 s: a - static GUI_FONT _aFont [GUI_COUNTOF(_aHeight)]; // Array of GUI fonts
8 W% Z9 o+ P5 S8 l8 o2 y - static char _acFamily [200];
% O) D5 t! U" _7 ~ - static char _acStyle [200];
. {! P, o4 L, j1 `6 G' R" q -
0 v. s4 T7 X! N2 w - /*********************************************************************
2 Q2 F+ t7 y" I6 L7 l - *$ P% b. q) G$ F7 O- R- i) U
- * Static code
; Z3 ? e8 c" W+ n- V" s - *5 V& S' E+ p5 J* W1 V
- **********************************************************************
. q+ z' n, Y) b0 V - */8 V/ [$ k' E$ I' \) N/ w0 ~
- /*********************************************************************$ ^5 f6 O! _( ?8 w8 ?
- *5 Q* `+ j( d) \& V# n6 [
- * _ShowText: B1 ]+ P5 t: e% R2 [# ?
- */
6 p0 p1 \7 e2 C. N) D3 y - static void _ShowText(void) {(1)
+ _6 e- }& l* [6 E/ _) u# X - int i;* F) D6 l2 }6 G3 ^1 s7 b" a
- 7 L6 w& n/ p9 ]3 R; a
- GUI_Clear();
" {; x5 e) I3 C; w5 U2 X - i = 0;4 x1 o; A- u+ O: ?
- GUI_TTF_GetFamilyName(&_aFont[i], _acFamily, sizeof(_acFamily));(2)
`. @, d1 k q - GUI_TTF_GetStyleName(&_aFont[i], _acStyle, sizeof(_acStyle));
3 \# B. W6 \! u; y - GUI_SetFont(&GUI_Font20_1);% O0 j9 K$ f* B3 v
- GUI_DispString(_acFamily);1 A. c8 B5 }( |& ^! K2 e) ~
- GUI_DispString(", ");
" q" z+ g0 u* C7 X - GUI_DispString(_acStyle);
2 H8 O# a) M- Z - GUI_DispNextLine();
0 V" k' Z+ D6 r3 V; m; M - GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);% E" O4 G5 V3 W/ }( y+ |! K {
- GUI_SetFont(&_aFont[i]);
% m5 I* Z5 n* o; H" \- f8 S - GUI_DispString("abcdefghijklmnopqrstuvwxyz\n");; V5 c4 W" l0 a0 c$ I/ E
- GUI_DispString("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");
" u# G4 i+ k% l) r% } - GUI_DispString("123456789.:,;(:*!?')\n");- Z* M8 b n6 @. [& \
- GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
, t+ K# m8 A. x" l' A - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {; I4 n* K2 `3 }$ Q& W
- GUI_SetFont(&_aFont[i]);% V2 n* l1 j, E6 ~) [7 G
- GUI_DispString("The quick brown fox jumps over the lazy dog. 1234567890\n");- ~: Y( S0 ^# K+ X6 j5 B
- }! \" @9 { Y: H
- GUI_Delay(1000);7 i8 J- T' k4 o" _
- }4 X% f0 g, k5 l; t I, e7 Q
-
8 i' L' I2 H5 C+ ^9 J* A8 @3 ~ T - /*********************************************************************
" S$ \7 t3 `" A; v: _. w2 K - *
- e$ C/ e6 s$ w! B7 J. t - * _CreateFonts: ^6 \8 Y% V, h- K0 v: \# e
- */
/ r0 A; N2 I9 Y2 {) B4 a5 A - static int _CreateFonts(const U8 * pData, U32 NumBytes) {(3)2 l" q" R; N1 K9 d- e/ a9 I3 B- L" Z
- int i;, u& Y5 `3 ]. m! z2 S t4 \+ K5 h
- GUI_TTF_DATA TTF_Data; // Only one GUI_TTF_DATA structure is used per font face* }: p5 x4 [$ k) d- V y1 j. x
- - B7 [8 I+ z8 {0 u; |2 K
- TTF_Data.pData = pData; // Set pointer to file data7 _+ q; B J& \" g
- TTF_Data.NumBytes = NumBytes; // Set size of file4 _ l- V- w) r$ ^ ^/ M5 H. ~' \
- for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {
- W6 M* u3 q1 k% v. E - //
/ N0 I9 L% f% I1 D( v- R4 { - // Initialize GUI_TTF_CS members
! C) {/ ] @5 @+ }$ H - //
. r4 U& N8 B; ~ E& ^% a - _aCS[i].PixelHeight = _aHeight[i];6 s# U( J/ i+ ^; [5 y
- _aCS[i].pTTF = &TTF_Data;- H1 I' {2 w! _( s& m
- //) Z3 r- v0 I; H' @% l4 j4 S3 ?
- // Create GUI font
; O3 o5 ~6 [: C4 X0 i - //
+ o" }/ t! G% T/ G - if (GUI_TTF_CreateFont(&_aFont[i], &_aCS[i])) {(4)
5 Y" \+ c1 o& c0 ^2 u# h - return 1;
' c/ ^0 s* i6 C7 x% j! N, H - }
0 s: I! V0 o, ~. F - }
) y ^/ t+ W, T2 r- p - return 0;% s; e6 G0 r, E
- }1 M3 b# S/ h& r
-
' v, n6 D( i* e+ N3 } - /*********************************************************************
7 V _6 X$ E- b - *
5 O! R/ o& E" g - * _cbFontDemo
. N7 ?( T4 [. i0 M) P5 }4 W. r - *
7 a) y6 B2 i7 ~ - * Function description& w4 Y# C1 h6 w0 `% r
- * The function uses the given pointer to a true type font for creating
0 P7 l1 S7 e& W* w$ e - * a couple of GUI fonts and showing the outline of the TTF font.
+ R% N- ~7 h9 A6 o! l7 {) I - *, O3 c( x: q+ _8 j
- * Parameters:
6 v" K) t. z) y& m# [ - * pData - Location of font file
( C" {& Q2 E: z4 ]! U - * NumBytes - Size of font file
: r- f H* p7 ]* G/ l& c* A - */
6 f2 G/ Z( u/ r: B" R6 I- L$ l - static void _cbFontDemo(const U8 * pData, U32 NumBytes) {(5)( f0 r c3 u, B
- _CreateFonts(pData, NumBytes); // Create fonts
6 @1 P9 X. W0 d6 J! ~ - _ShowText(); // Show some text
) X% |1 ?8 D- Z3 J - GUI_TTF_DestroyCache(); // Clear the TTF cache, P, e+ q1 m4 n5 {" d3 ]
- }+ U$ Z2 j }0 n' t( [6 t( R. A
-
6 R) R# P( ]$ t8 D) K. e& v - /*********************************************************************, a" n9 X2 o- C' m
- *
( n! {: I( Y5 m$ S) z Z& P) m - * _IterateOverAllFiles; s3 C- p5 H" y0 k: K# Q" `' a! h
- ** ~3 T2 a" |& ?" S. [& z% ?1 j
- * Function description0 E5 l$ {2 y3 \: j
- * The function iterates over all files of the given folder and the
3 H) l% N! u" z8 B' G - * given mask, reads the contents of the file and calls the function
( {5 ~9 ?6 n" V I1 b% P# j - * pfDoSomething() with location and size of file data.: A/ e/ B7 b: ?# g, k$ G
- * Can be used under Win32 environment only.9 G# q Z( h( D1 O4 y- {% G. s4 k1 s
- */! J! t2 M. ], }1 o+ _
- static void _IterateOverAllFiles(const char * sFolder, const char * sMask, void (* pfDoSomething)(const U8 * pData, U32 NumBytes)) {(6)
; M/ ?9 R' ?% |* g, I* N4 U - GUI_RECT Rect = {0, 10, 1000, 1000};8 }8 q1 n" Z ] h; B& C
- char acMask[_MAX_PATH];
* F" h. o ^. u7 \. \9 f - char acFile[_MAX_PATH];. ^6 N3 T* j1 ]" q3 `% {1 D6 k) A
- WIN32_FIND_DATA Context;% w) |6 m& ?! X7 ~- U
- HANDLE hFind;
" h3 p; ~2 b1 P) D: h8 {9 ~9 G - HANDLE hFile;
8 c7 @+ M# s9 m3 n - U8 * pData;0 E o2 ? \+ U
- DWORD NumBytes;# z, S* T: Z+ J! |! I( D
- DWORD NumBytesRead;
7 h& ]$ E8 c! D -
9 z* Y) `9 P4 p6 G( Y, k6 F" N - sprintf(acMask, "%s\\%s", sFolder, sMask);" |$ a3 }( i. D% m: }* w e
- hFind = FindFirstFile(acMask, &Context);" f2 P8 K' }) f4 c
- if (hFind != INVALID_HANDLE_VALUE) {# m: M+ d& ~3 T8 L. y+ p
- do {! f" b6 V; b6 @' O
- sprintf(acFile, "%s\\%s", sFolder, Context.cFileName);. v! C& A! O$ w
- hFile = CreateFile(acFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);- ]# L' }) R( e$ T& a0 ?
- if (hFile != INVALID_HANDLE_VALUE) {2 ^0 V& L9 o9 D5 U p4 V
- NumBytes = GetFileSize(hFile, NULL);. }3 H. X7 T) q1 y u' U
- pData = (U8 *)malloc(NumBytes);6 X" O# l6 X1 o) e: D
- ReadFile(hFile, pData, NumBytes, &NumBytesRead, NULL);
4 p5 }; T+ a0 _8 ~9 Y. s2 A% S - pfDoSomething(pData, NumBytes);
\: _0 j. V' f% z b - free(pData);
! P$ I9 r- K2 { - }7 m$ C# i" G; O9 w8 O
- CloseHandle(hFile);; R; q4 |% q$ O- q! \: C
- } while (FindNextFile(hFind, &Context));
3 V4 y8 p0 ?% l - }& b a0 M4 x. ]. L/ f1 B( Y) ]
- }& I$ e$ `; e i- P- L! P
-
- Z* f' W* j; |* ^, U% w - /*********************************************************************, P3 b2 M9 Z: {+ ^/ ^* i; [$ y; Z
- *
# o$ ?( F2 h8 z- n# x0 H* Z- d/ G" _ - * Public code' O3 o; J! a% g8 R
- *
# I( g' ]. M- Y' C- X( b% J - **********************************************************************+ m2 l# h3 @' J, y$ `) o& ~8 T
- */
# Q7 Z* s( T% I - /*********************************************************************: T3 H# h5 m7 Y4 M7 ^1 j
- *2 ? b9 U# T/ i% O& ]" z# p5 J' E B
- * MainTask. n) u) _ h) }% H. S7 M
- */
/ b' `2 u, M. z: G' t/ W# E - void MainTask(void) {) C% ^5 g3 Z3 d( X6 A
- char acPath[200];7 l" v+ b# s' t7 y# Z" O
- & r. i1 I% P2 i
- GUI_Init();
- c! E+ [3 q9 B. y6 H% x - //1 f. ]8 T5 t' I: R( l" n$ Y/ \7 U, x
- // Set colors and text mode2 ^* c5 ^7 N0 F3 e, m/ G
- //
& {: r! y: s. J4 p3 w9 [- M - GUI_SetBkColor(GUI_WHITE);
4 P4 b; m& H0 F: |6 K3 O - GUI_SetColor(GUI_BLACK);
/ d6 L1 Z( c7 O' { - GUI_SetTextMode(GUI_TM_TRANS);
: Y+ B( {9 R7 I, | _8 z' Q, [0 v7 N - //% u2 N1 w/ ~% \
- // Get windows system directory and extend it with '\Font'(7)
3 A$ y6 g8 o k; X/ } - //
, b! L" U" _# W' t- _$ V t - GetWindowsDirectory(acPath, sizeof(acPath));
# S( Y5 H3 z* J' ]4 C6 [' z( o - strcat(acPath, "\\Fonts");" F' ~/ A, E) _8 b4 P
- //" R0 g: x. Y% E& U5 W3 [
- // Iterate over files and call _cbFontDemo for each file" p+ e4 V2 p/ G
- //
6 A: C/ S* O5 C - while (1) {; S/ x1 {8 Q( a6 S( E# l4 R
- _IterateOverAllFiles(acPath, "*.ttf", _cbFontDemo);, ~% z8 C8 J& L% c6 c# E* ^0 U; v: j% c
- }
9 g, n/ Z7 H! j; B# @* W% l - }( i: G9 {8 n8 O. R0 l3 k
- ! ]# T2 |0 r, q! \7 X! y
- #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. 获取电脑系统中字体存储的路径。 实际显示效果如下(这里只贴了一个截图) % e8 C3 L R# I5 `% b( m3 T+ A
|
% D# [7 J" c1 t+ Z: f
22.4 移植到开发板上显示5 f7 h2 v' {" O/ u+ }" F& O
^: _1 L7 F% `
22.4.1 第一步:从官网下载矢量库
. W- ^* H4 ?' V" I0 }& `, ?