特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
B: k4 i4 D+ s$ P5 J# ~" b4 G第22章 TrueType矢量字体
8 d+ x* P; K" T: g3 n) O+ 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_TEST8 E1 A0 K0 ]6 V' W/ p
-
0 \& x7 ^0 N1 a( T) I - #include <windows.h>8 G0 U" ?& W" A9 L4 K
- #include <stdio.h>
& ^' h$ u- M A2 M: c - #include "GUI.h"
2 Y, V, S6 ?) i6 b -
) i" N% f% [1 f* S* K - /*********************************************************************
9 C, d5 d; g% `5 ^2 q9 s, M4 w3 | - *
# x' W* o8 J$ d" t" ^9 k - * Static data
- ^* l' _( [' J5 B c) v+ F - *) I! b$ @# [6 x" T9 {" {
- **********************************************************************
9 n5 C8 Z0 p+ H% f7 `9 i- U - */
8 Q2 W( x" S7 P - static unsigned _aHeight [] = {16, 20, 32, 48}; // Array of heights used to show text; }/ b. y: @6 i- c. Q) E
- static GUI_TTF_CS _aCS [GUI_COUNTOF(_aHeight)]; // Each GUI font needs its own GUI_TTF_CS structure$ w+ w8 c! |$ S, o _
- static GUI_FONT _aFont [GUI_COUNTOF(_aHeight)]; // Array of GUI fonts
e6 L" w1 U( {. l8 i - static char _acFamily [200];
5 H4 e& T9 G" ~* R - static char _acStyle [200];
: P" x( B6 H, F( b -
v" ?3 c5 d1 J; q$ t - /*********************************************************************
/ M6 a9 @9 H& B - *6 C( I" k$ }: |! h% d/ f
- * Static code
* d z9 l" {! w8 i' g4 b H - *2 r7 Q* A0 v3 T8 ^( @. b
- **********************************************************************
" q! _% {" L# T+ _& I! W1 N - */! i+ E" f# Z) @7 ~; t" a
- /*********************************************************************
, W2 R. w2 ]3 A+ p1 @ - *
! n8 A1 C `0 ~6 q! u - * _ShowText
9 l( f% U5 {5 q" S. O3 J% d - */
6 Q3 F4 {) c0 A# U# K, E - static void _ShowText(void) {(1)
) i1 I: [- A7 F& N0 { - int i;! X$ V1 C/ N X/ _3 @; k1 [5 K
-
/ q' a" Q# ^( C - GUI_Clear();
6 F# @6 g7 F, Y - i = 0;. V. N8 ^8 I7 v4 m0 v0 w( ?! ]
- GUI_TTF_GetFamilyName(&_aFont[i], _acFamily, sizeof(_acFamily));(2)
% M4 [" q" M6 ]. e" v - GUI_TTF_GetStyleName(&_aFont[i], _acStyle, sizeof(_acStyle));
# N l2 l; i/ Z) R* M7 ] - GUI_SetFont(&GUI_Font20_1);
/ g0 j+ F! I0 x - GUI_DispString(_acFamily);. r/ {) {! q3 i1 i( Q+ C
- GUI_DispString(", ");
8 S0 o$ t% U6 u - GUI_DispString(_acStyle);
0 j) x* k5 [$ q/ i/ }5 p - GUI_DispNextLine();& N1 u `0 N" v# E! c( f4 s. M1 r
- GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);
`, f# m- Y; |7 u - GUI_SetFont(&_aFont[i]);1 M! H- u* e5 S2 }, p" m6 |" S
- GUI_DispString("abcdefghijklmnopqrstuvwxyz\n");
$ C! N( B% U- F" Y/ n! n/ o - GUI_DispString("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n");* i9 N- H4 |' C8 x! s0 d
- GUI_DispString("123456789.:,;(:*!?')\n");
0 b* @9 X; e) E( q2 c H5 U7 S) A - GUI_DrawHLine(GUI_GetDispPosY(), 0, 0xfff);- c* P7 U Z* o! b4 Z8 e2 b7 F
- for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {
* n$ @) J, @: E - GUI_SetFont(&_aFont[i]);
8 @5 N3 s" J% C; c4 b - GUI_DispString("The quick brown fox jumps over the lazy dog. 1234567890\n");: f( f7 [( `( I2 |
- }! W+ p! h' Z G$ A
- GUI_Delay(1000);- E e) ^/ w- o0 B# K0 A0 e
- }( c0 z" o h/ d/ F
-
& ^; U) l8 ? @0 }: l9 r( g - /*********************************************************************) \* G- h7 E" z9 X4 V
- *6 T) Z3 ] y2 r( K
- * _CreateFonts( `/ [( p" `9 B+ J; t/ l6 n
- */
" o7 F7 B7 v# x# f - static int _CreateFonts(const U8 * pData, U32 NumBytes) {(3)
; R- g) C# ?, w7 \7 a) M8 z - int i;: m& P7 T7 ?& c6 R
- GUI_TTF_DATA TTF_Data; // Only one GUI_TTF_DATA structure is used per font face; W, a3 b) u2 Q1 d; j
-
" S; e6 R; D" k0 I0 L - TTF_Data.pData = pData; // Set pointer to file data0 c" B+ {5 O4 L1 b% w; C
- TTF_Data.NumBytes = NumBytes; // Set size of file
5 S+ x7 @1 v- Y* P/ r0 J - for (i = 0; i < GUI_COUNTOF(_aHeight); i++) {
- `" L1 y$ x3 e3 T# r" w; ]1 m! Q* v9 i - //
3 f: W9 P" s1 V1 N. B9 G* E - // Initialize GUI_TTF_CS members t6 a7 C9 C; \ G
- //
1 w8 d8 H9 j. ~. P6 ^ - _aCS[i].PixelHeight = _aHeight[i];- s, p1 h0 b0 t9 ] g6 S" A4 q$ V
- _aCS[i].pTTF = &TTF_Data;& Z% D( P4 c5 Y' b, h7 W) Y
- //9 W1 R. k& X c6 |/ W A! f" G9 v, b
- // Create GUI font2 E2 j9 D! `) P w- P- m9 x2 I" Z" {' ]
- //$ v2 c2 X0 l9 \) P
- if (GUI_TTF_CreateFont(&_aFont[i], &_aCS[i])) {(4)' Y7 I Q, G2 X1 X- ?6 l
- return 1;
/ N2 V: a* a q0 ~0 ^ - }
* E8 {& x4 c3 Q! P - }
9 r* e- K S) Z G - return 0;/ E' Z( H. u' {, ~- X) W; ~
- }
: e I8 p% ~0 W0 \; h9 y+ H - . O2 H" `( H( K( Q
- /*********************************************************************1 @* N( o0 B2 `4 G' K
- *
+ z' R+ {1 D! F9 m9 ?, V% _3 { - * _cbFontDemo. ~8 K( ^% I; I2 | T* D" W
- *
( K# a" s: b, a6 S& U7 v- ~+ [ - * Function description1 Z+ k; i/ s* J. n3 f, A
- * The function uses the given pointer to a true type font for creating4 W7 [, W0 ?. v& g1 k' b; q& K
- * a couple of GUI fonts and showing the outline of the TTF font.. J: b) s0 N/ r
- *% P* }0 B1 l) `! h8 k5 h8 E! T+ D
- * Parameters:8 W' z% v/ G3 l: P4 s
- * pData - Location of font file
, T6 B6 q; v5 M6 z3 E0 q( O% l# h - * NumBytes - Size of font file2 t! E1 z) e. E: [) ?: u
- */
. O$ ]9 k0 p9 U( N7 U - static void _cbFontDemo(const U8 * pData, U32 NumBytes) {(5)
; Y; X- N4 t& {1 b7 H' N3 g - _CreateFonts(pData, NumBytes); // Create fonts& \9 e' @5 z! s; v `
- _ShowText(); // Show some text
$ `' e" b6 w3 }* W - GUI_TTF_DestroyCache(); // Clear the TTF cache
# B4 F" a3 X) c - }
. }7 S g$ A5 H: Y -
! O8 \3 X( y, N \" t" @8 Q - /*********************************************************************( `- H$ z1 [* ~; Y- ?# f
- *4 Q4 {8 _4 n, v
- * _IterateOverAllFiles
+ h9 n* [+ B j0 X, n* C. T1 Z- C% N - *
4 Z; Q0 i+ W7 _( M5 K, { - * Function description
( E8 n. p: p2 c d - * The function iterates over all files of the given folder and the0 V* N9 P' e. K
- * given mask, reads the contents of the file and calls the function, W! s d) u0 o6 J4 n
- * pfDoSomething() with location and size of file data.
" r5 [) g; O& f7 ~1 P - * Can be used under Win32 environment only.. C2 X, q( P! S$ _! l, q3 G# h0 |# f
- */
5 x+ F7 E" }6 {# e5 I1 X - static void _IterateOverAllFiles(const char * sFolder, const char * sMask, void (* pfDoSomething)(const U8 * pData, U32 NumBytes)) {(6)' t, o8 B5 ? L) O9 l; s( j- }) s
- GUI_RECT Rect = {0, 10, 1000, 1000};
: I! ?& @, t, a( M/ T - char acMask[_MAX_PATH];7 H1 a* v& t [- Y! C1 C8 v
- char acFile[_MAX_PATH];- x+ S" t9 }" J) I) l: `
- WIN32_FIND_DATA Context;/ D) ]$ o5 _' U6 X
- HANDLE hFind;
$ b! ~! A/ Y: L, p1 B3 Q$ i - HANDLE hFile;
, C5 s/ \0 N u# Y; U - U8 * pData;5 v) z4 u/ N3 q; G. I! q
- DWORD NumBytes;+ b5 X0 P2 `/ h+ g; M/ C
- DWORD NumBytesRead;
, Q3 `' V' m/ X+ a' P6 ? - 5 E. w4 D3 c- M& W
- sprintf(acMask, "%s\\%s", sFolder, sMask);
2 ~# q X. s2 z4 C - hFind = FindFirstFile(acMask, &Context);& l6 r' m$ k# \ ?* R0 N
- if (hFind != INVALID_HANDLE_VALUE) {& W3 Q4 D1 ^4 {; V5 K2 @2 W
- do {
! J9 v5 g. o g1 t, z4 O - sprintf(acFile, "%s\\%s", sFolder, Context.cFileName);
1 c; |# f8 L6 P* }$ u% y3 C - hFile = CreateFile(acFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
, b6 Q4 A( Q5 a+ Z. F* P, w - if (hFile != INVALID_HANDLE_VALUE) {5 J1 i' B8 z! Y. o
- NumBytes = GetFileSize(hFile, NULL);+ k4 q5 J3 e1 S" X" C7 h
- pData = (U8 *)malloc(NumBytes);: z+ ?9 }" L2 c8 Q
- ReadFile(hFile, pData, NumBytes, &NumBytesRead, NULL);. m- y/ w& x9 N$ g
- pfDoSomething(pData, NumBytes);* ~% C; p' S/ l8 J/ t
- free(pData);; k8 z m, f% j0 h/ O
- }
# k6 C4 o+ H- D1 E6 \- t# ~ - CloseHandle(hFile);
' I+ J o% U* H4 M. n+ R' q% w - } while (FindNextFile(hFind, &Context));
/ T8 G f* M2 N- X F- T" i* x - }* x4 T; O' v: w. Z, [4 O$ S. N( Y
- }. H6 q* w) Q- V3 n& {0 {
-
1 L1 K9 W7 r9 M0 b0 M: \ - /*********************************************************************
b2 {+ w4 D- Z( p2 S: L9 s- ? - *
/ h# U0 ?1 o" r L8 U6 A - * Public code
& z: u& T5 K7 Z% ~ P - *6 y- w& R8 ]9 V
- **********************************************************************
% O$ c8 H" ?) x- ^- p1 Y0 H/ f - */
@5 A* b5 T0 }8 ~6 _ - /*********************************************************************7 S6 O, B! a' ?" c$ j8 h
- *
. z. r5 g n7 }4 L) [ - * MainTask2 f% T! b) u* m: ?& r
- */1 x8 f5 N) H1 q& w
- void MainTask(void) {
7 M( V4 y+ u8 O& T5 }4 o - char acPath[200];% V2 f8 u V* f1 a9 G' F {1 q
-
2 x" u; z6 \5 d! _( O - GUI_Init();
: ]$ W" G# K3 \2 B. ?. Z! n% Z$ Q - //( o) g: l6 _6 \: I% |
- // Set colors and text mode* n9 v9 y( f8 b* I
- //
@# v9 S$ M+ e6 P# i0 h$ Y - GUI_SetBkColor(GUI_WHITE);3 ]. b9 Q3 _& q* o9 N
- GUI_SetColor(GUI_BLACK);
7 @( {% d B2 H) h$ p6 m - GUI_SetTextMode(GUI_TM_TRANS);
. W7 Y7 B, I- E; L: r+ g6 j - //$ I/ S9 O3 W9 E6 X% V+ ~2 {
- // Get windows system directory and extend it with '\Font'(7)
/ Z2 G# A% H* t& \# Y; p5 @ - //) S$ `' P3 y, m
- GetWindowsDirectory(acPath, sizeof(acPath));
" p7 T+ [; b) C) i: A( V( A - strcat(acPath, "\\Fonts");
) T! T. t) U& V ~% r - //
8 _; h# x0 c$ ^5 z+ } - // Iterate over files and call _cbFontDemo for each file' |7 q Z) [- Z R3 t' }, g. K9 C
- //# }+ l' W3 p% Y# v; Z/ |- F4 K* ?/ b
- while (1) {
. \5 ~# t- n+ ^: D7 C) f1 j - _IterateOverAllFiles(acPath, "*.ttf", _cbFontDemo);
1 M" P. r2 Q- W0 |( {/ L - }
" t. i6 G) m$ Y7 N - }
8 ?/ L m# V' } -
1 @. q( K3 g/ O8 e - #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. 获取电脑系统中字体存储的路径。 实际显示效果如下(这里只贴了一个截图)
2 G- k! y5 O8 N/ ]. A2 T3 t |
N, C5 O; O! n( c8 C0 i i0 w* v8 g
22.4 移植到开发板上显示$ C# d4 v( [. E/ p g
z8 l* I9 ~& F5 Y6 ?3 J+ G+ b; m
22.4.1 第一步:从官网下载矢量库
; \, h: x. j: |* M4 O$ l1 _2 j