特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
: z/ J/ F. A! z) p. ]3 k第22章 TrueType矢量字体 % l+ q! f3 w* q V: k0 i6 t
本期教程跟大家讲解矢量字体的相关知识,矢量字体最大的好处就是可以任意放大或者缩小字体,而且字体的显示效果不失真。矢量字体的缺点就是不适合用在小型嵌入式系统中,极其消耗内存。 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# A+ Y1 u6 ] v% l6 D: O7 H( x( \
- - F" d9 P+ H" H/ r- h5 q* K: v2 u
- #include <windows.h>
5 r7 H' c4 T! O$ L) w& O/ v - #include <stdio.h>
2 J! k+ g# C, X* F. k4 v - #include "GUI.h"
! x; k1 Z: m0 i' Z# o$ i -
9 S4 Z* V3 g: p8 ~& M2 G - /*********************************************************************% U4 j' }4 u' X3 q0 ?) H$ A
- *
3 y" m- r: ] @0 V! { - * Static data4 D- }1 K& V+ i
- *
& j3 d: B" ?- v$ u - **********************************************************************
4 t+ R# L- Q3 I& i- V+ S- u - */
: V# E+ @4 |, X% K4 |% d - static unsigned _aHeight [] = {16, 20, 32, 48}; // Array of heights used to show text* Y: V% L6 M L/ S
- static GUI_TTF_CS _aCS [GUI_COUNTOF(_aHeight)]; // Each GUI font needs its own GUI_TTF_CS structure
& H" J u# p- o - static GUI_FONT _aFont [GUI_COUNTOF(_aHeight)]; // Array of GUI fonts
, l" g0 s6 P- H/ R7 M8 E; R - static char _acFamily [200];/ ?: H6 u7 U; t+ i4 B* l
- static char _acStyle [200];
* c. z0 ` \0 i -
8 Y9 r! p6 A4 k* p; h8 a - /*********************************************************************
( S6 F8 E. v4 ~8 N - *0 H5 l; E6 M% {" ?: ~+ `
- * Static code
% n6 P! x9 T3 M" \- h* Q' F - */ N0 y* x- k1 o( `; T
- **********************************************************************
1 _8 U% U1 @( [" ^0 v - */) S( a/ g+ t' {; u+ X
- /*********************************************************************
3 D3 Q% p& t" v m; a% l - *
0 R4 ^- C8 l/ Q! ^& A- K - * _ShowText
# O' I- i! ]8 W5 W$ r - */
; i1 V7 G) P ^% }' ]& A, p - static void _ShowText(void) {(1)- T7 ^) O6 }! q+ @ L8 O i
- int i;
* r. c, X9 ~- [. L. X5 ~( h$ k -
8 O! O: b! y. V S7 ]3 R8 ? - GUI_Clear();
( s$ |1 Z" Q g4 n/ |* Q+ O3 t - i = 0;
; [" ]6 y( S( x- S( q, z - GUI_TTF_GetFamilyName(&_aFont[i], _acFamily, sizeof(_acFamily));(2)7 L B9 X4 `* d0 a. W' w/ @
- GUI_TTF_GetStyleName(&_aFont[i], _acStyle, sizeof(_acStyle));
# _5 N X. e* o8 `: ^ - GUI_SetFont(&GUI_Font20_1);
1 z, `$ n! ~8 [1 y - GUI_DispString(_acFamily);
; C$ L, E( M7 v6 N - GUI_DispString(", ");
x1 O0 C x2 o2 F& L - GUI_DispString(_acStyle);2 a! a: g/ }! E
- GUI_DispNextLine();6 b0 h4 m/ @ z) O; i ]' U* s
- GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
z# b2 Y& ^% }$ z% W - GUI_SetFont(&_aFont[i]);
6 C% A6 `1 y* P; o g3 Y1 t" @# i - GUI_DispString("abcdefghijklmnopqrstuvwxyz\n");2 L% r$ }9 M5 @# c. N5 y
- GUI_DispString("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");0 H0 ]) d9 L! A- j% Q8 V
- GUI_DispString("123456789.:,;(:*!?')\n");
. w% \5 k+ m% Q7 J: @8 K8 k8 V - GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
6 Z" U$ \0 P$ {9 G/ N- c6 z - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {& O! {( I' P1 l& C# [! X" i
- GUI_SetFont(&_aFont[i]);
2 t3 Z- X2 u) Y% ] Y: ?- Y7 k - GUI_DispString("The quick brown fox jumps over the lazy dog. 1234567890\n");
; I! @: E, W+ I; L: r) x0 ? - }/ J9 x$ u- k% o# ?" q) [3 N
- GUI_Delay(1000);$ \( a/ M& _% M C8 y G
- }7 \; ?% F' [" b* R1 q
-
9 p$ T8 M; I) Z5 q4 o2 ^/ a% R - /********************************************************************** e5 t7 n- z6 T6 }/ u) O
- *
6 q4 t7 B& s- ?" ~& i$ u) h - * _CreateFonts5 Q; b4 R$ k( d( i$ c2 r( Z4 q
- */6 g6 e+ F+ d& B/ t5 U
- static int _CreateFonts(const U8 * pData, U32 NumBytes) {(3)
H" M, E3 Z& X8 ~+ x* q - int i;
; P3 v* w" E" \3 D - GUI_TTF_DATA TTF_Data; // Only one GUI_TTF_DATA structure is used per font face
; l( L6 ? T9 p- T -
- R2 t0 g- p; _2 ^% c# W, _8 ^/ }1 @ - TTF_Data.pData = pData; // Set pointer to file data
$ u$ i- r$ y* E0 B- M s4 R1 G7 s - TTF_Data.NumBytes = NumBytes; // Set size of file
8 Q1 K2 f4 [) O5 y. c, @ - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {) f+ d/ f# h |5 g
- //$ I {# o0 f$ D. z/ O
- // Initialize GUI_TTF_CS members
! ^: Z( K$ E7 e; t - //: h6 v- H' V' V X& d' ^/ V- C# T
- _aCS[i].PixelHeight = _aHeight[i];- K3 A( i9 C, W6 k2 S
- _aCS[i].pTTF = &TTF_Data;
* [. B. _8 o0 n Q* U - //
! y6 f5 F! ~4 [" N) z# { - // Create GUI font
, n4 Q: p" r4 ?" ^, s - //( W+ F$ X2 F7 p+ k
- if (GUI_TTF_CreateFont(&_aFont[i], &_aCS[i])) {(4)
8 c& c1 m S% x- G' g C - return 1;
% U* T5 V8 Y5 P6 \0 N6 G - }4 Q3 s* w* e2 @& S
- }+ |- n8 @, O5 s1 d
- return 0;6 n% G( `1 y8 D1 @" d0 `
- }
5 M8 F7 F7 m0 B9 L - & b5 f% n8 ? o& k, M
- /*********************************************************************. P' w* G1 V* C7 o6 t* k: H
- *
" ~" z4 v4 f) u2 x6 H% Q - * _cbFontDemo" O, h% T+ m6 @7 H4 g8 R
- *' v) ~1 {6 [7 e# v( J
- * Function description
; n0 q# h" |) h) `4 n+ c7 T0 f - * The function uses the given pointer to a true type font for creating
" g/ v! D" V" q- G1 ~- o - * a couple of GUI fonts and showing the outline of the TTF font.
7 p/ V2 W3 c4 @ `4 X7 B. B - *$ Y* R( T: q; k4 g+ b2 B0 d) R
- * Parameters:4 P* m1 b& e+ {: `9 P* }8 q; V5 _2 |
- * pData - Location of font file2 d9 U2 ^; N" a2 ^
- * NumBytes - Size of font file
A! l) x. D1 W1 l+ E - */# Z$ G( r7 N/ p) r y+ _7 D
- static void _cbFontDemo(const U8 * pData, U32 NumBytes) {(5)3 L' Y# k. K, q
- _CreateFonts(pData, NumBytes); // Create fonts
3 Y; T( C3 x: b' z6 o - _ShowText(); // Show some text# n# d( Y* n% H1 E$ W
- GUI_TTF_DestroyCache(); // Clear the TTF cache
# X( Z+ h" Q! F1 v3 O2 x% p - }
[ @: s2 A! e. K. ]* H - 5 F( r/ S" C, u0 g0 N* \
- /*********************************************************************
/ `4 ]( A% H( d - *
4 U: H' V( ^2 n: Y - * _IterateOverAllFiles
2 |2 C0 y% ?& X& k! |$ _ A; E: V+ d - *
" b g( x( b* \' _ - * Function description
! G# {& O! {* W5 ]& v$ i - * The function iterates over all files of the given folder and the
' u$ V- b6 b- ?/ j9 y, ` - * given mask, reads the contents of the file and calls the function
4 ?8 b5 M$ ~: D" R2 _: g - * pfDoSomething() with location and size of file data.8 U( w; Q7 d" [9 K3 C! w2 K8 D$ ]( y
- * Can be used under Win32 environment only.
5 P+ ~4 C9 m8 y! @. e- ~/ g - */
) g6 ^$ L8 V5 { - static void _IterateOverAllFiles(const char * sFolder, const char * sMask, void (* pfDoSomething)(const U8 * pData, U32 NumBytes)) {(6)7 B& e" ?$ w8 ?1 b4 ^
- GUI_RECT Rect = {0, 10, 1000, 1000};
: J( M) i p, T1 [- |: y - char acMask[_MAX_PATH];
+ c4 g: [7 L' L - char acFile[_MAX_PATH];
% a- I+ h. w! `8 a - WIN32_FIND_DATA Context;1 I" k# g, A8 R+ G' }# K$ t# w# D
- HANDLE hFind;* p# ~# o9 p# Y/ H" L, c
- HANDLE hFile;( X" ^* f- O l- W
- U8 * pData;* C0 ~6 B" n) K
- DWORD NumBytes;
! Q3 j ~+ Z0 D - DWORD NumBytesRead;6 G! M: k+ F( F( K5 j ~$ y
- - H4 ~1 d+ K& J/ c9 b9 z
- sprintf(acMask, "%s\\%s", sFolder, sMask);
, n3 Z; p2 @/ F - hFind = FindFirstFile(acMask, &Context);& H7 [: @. _% p5 M0 b% [( [$ j
- if (hFind != INVALID_HANDLE_VALUE) {
1 x1 ]1 A) @0 r& U5 X" [- l" X - do {: w( J7 X0 P# n$ Z$ n! F
- sprintf(acFile, "%s\\%s", sFolder, Context.cFileName);
/ ^- T" F8 f) i( d1 { - hFile = CreateFile(acFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);. C% @7 n# j S- S Q" ~7 C4 C5 ~
- if (hFile != INVALID_HANDLE_VALUE) {6 D0 ~1 W5 V5 g, W1 y: h
- NumBytes = GetFileSize(hFile, NULL);& n2 s) s O) I+ I0 ?
- pData = (U8 *)malloc(NumBytes);! [! U; D ?7 n" N6 i1 Y, V
- ReadFile(hFile, pData, NumBytes, &NumBytesRead, NULL);4 |5 e+ h$ U* f+ ?* I
- pfDoSomething(pData, NumBytes);
; C$ j6 o% H O% w9 Q - free(pData);" Y; q+ S. J2 p) j. t7 k
- }; A7 n0 X$ ^7 `. C6 k. R, C
- CloseHandle(hFile);+ C) F6 n- o' P$ l
- } while (FindNextFile(hFind, &Context));
: ~0 ^& m5 z2 s - }' s3 W6 I6 i$ Y/ A$ p
- }
( q/ g. v9 ?: L! Z: \/ ` -
1 e0 p4 s4 Z! g- j3 L, e - /*********************************************************************
3 f* F' w( {/ c4 p8 \ - *+ ~; N6 L3 {8 @8 ^1 b
- * Public code$ U& d; o- Y" o; Y7 D
- *$ A: B6 u' v) o0 w
- **********************************************************************
& Z# d9 {2 k6 H- P* K7 p, Z( ^ - */
0 Q; y: I0 r; T! q1 } - /*********************************************************************
" l2 d5 o2 s- V$ Z' v' S6 L - *
- Q8 ]' t4 S& C# ]" b. ~2 j! V6 j$ F* b - * MainTask
0 I, h( Y" ]1 l% [5 ]2 I F/ H - */& ~; _& f9 |6 W7 ^
- void MainTask(void) {
! F% S' z' ^0 q! e l8 K, {4 f. P - char acPath[200];. E2 p& |. _/ q0 {( q; \8 j
- ! B: j4 R1 g, O
- GUI_Init();& `; E% j6 b9 @% L3 d
- //
1 C2 y7 N$ A1 G0 J7 O7 i* n2 {4 L - // Set colors and text mode7 W7 S1 n7 v+ S) |- r2 Y
- //# E9 r% U" \1 U* S: u: l
- GUI_SetBkColor(GUI_WHITE);
" B9 ]3 y. ?, c/ s4 P( t - GUI_SetColor(GUI_BLACK);
, Y. P! L5 q$ E0 v: f - GUI_SetTextMode(GUI_TM_TRANS);/ ~! f& [( A. A3 W. P
- //
; Y( p+ \' ^) _* }) X - // Get windows system directory and extend it with '\Font'(7)' l, | `$ p* M6 K L9 ?2 M4 q
- //
( Y5 R9 a* A# h: g7 _7 b# ] - GetWindowsDirectory(acPath, sizeof(acPath));; m5 S) }' y9 `/ u2 e0 m
- strcat(acPath, "\\Fonts");
, x v3 N( F" A$ r6 ^ C# l2 ` - //+ V i7 }! W5 A" L. ?% c: X
- // Iterate over files and call _cbFontDemo for each file& B! ~7 j( Z; u
- //. Z2 O# }/ G5 t5 f4 n
- while (1) {, S( u+ o: @$ Y# i( N# u
- _IterateOverAllFiles(acPath, "*.ttf", _cbFontDemo);, F* ]3 f0 U9 O4 ?+ ?$ U `1 E
- }
& D/ Y1 J8 w1 O! s$ L4 C - }0 v% q0 s# D9 r* d. s* W
-
& W) ^2 Z8 N/ D4 F9 f - #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. 获取电脑系统中字体存储的路径。 实际显示效果如下(这里只贴了一个截图)
3 a5 L# T# @6 v* @+ R- E& s$ A |
* Q0 {9 ]5 o" u/ v) C0 P
22.4 移植到开发板上显示% ?/ P$ g! U- n1 n( Y- g: _1 L
22.4.1 第一步:从官网下载矢量库
1 }% Z# u0 k/ D- Y/ ^