摘 ?要:嵌入式設(shè)備上常用的有兩種類型的字體:點(diǎn)陣型字體和TrueType類型字體。點(diǎn)陣字體很難進(jìn)行縮放,否則會(huì)失真,而TrueType文件并不存在這個(gè)問(wèn)題。但因TrueType字體文件較大,并不能直接使用在嵌入式系統(tǒng)中。因此,在使用TrueType字體前須對(duì)其進(jìn)行適當(dāng)?shù)亩ㄖ?,只選取用到的字符,這樣可以使字體文件的大小減小很多,更適合使用在嵌入式系統(tǒng)上。
關(guān)鍵詞:嵌入式設(shè)備;字體文件;TrueType;造字程序
中圖分類號(hào):TP311.1 ? ? 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):2096-4706(2019)17-0005-04
Abstract:Two type of fonts are used most on embedded device,the lattice and the TrueType font. It is almost impossible to resize the lattice or distortion will occur while there’s no the same problem on TrueType font. However,the full size TrueType font are usually too big to be used on embedded device directly. Therefore,TrueType fonts should be customized properly before using them,and only the characters used should be selected,which can reduce the size of font files a lot and make them more suitable for use in embedded systems.
Keywords:embedded device;font file;TrueType;font program
0 ?引 ?言
TrueType字體現(xiàn)今在PC機(jī)上的使用已經(jīng)非常廣泛,然而在嵌入式系統(tǒng)中,字體主要還是以點(diǎn)陣型為主。究其原因主要為嵌入式系統(tǒng)資源有限,而TrueType字體占用資源和空間較多,雖然嵌入式系統(tǒng)的資源和性能較原來(lái)已經(jīng)好了很多,但是TrueType字體動(dòng)輒幾十兆的大小還是太過(guò)龐大。隨著顯示精度的提高,點(diǎn)陣型字體已無(wú)法達(dá)到顯示要求,TrueType字體取代點(diǎn)陣型字體已是大勢(shì)所趨,為了克服TrueType字體文件較大的難題,在使用TrueType字體時(shí)必須對(duì)其進(jìn)行裁剪,只選取字體文件中將來(lái)會(huì)用到的字符重新生成新的字體文件,以減小字體文件的大小[1]。
1 ?TrueType字體簡(jiǎn)介
TrueType字體技術(shù)是由蘋(píng)果和微軟聯(lián)合推出的一種新型數(shù)字字形描述技術(shù),用數(shù)學(xué)函數(shù)描述字體輪廓外形,含有字形結(jié)構(gòu)、顏色填充、數(shù)字描述函數(shù)、流程條件控制、柵格處理控制、附加提示控制等指令。其字體外形輪廓采用二次貝塞爾曲線,相對(duì)之前PostScript等字體,曲線方程次數(shù)降低,但配合其豐富的指令集,在實(shí)現(xiàn)輪廓曲線光滑性的前提下,大大提高了解釋器的工作速度。加之其公布字體文件結(jié)構(gòu),可實(shí)現(xiàn)在不同系統(tǒng)間進(jìn)行移植并方便用戶加入已實(shí)現(xiàn)的字符,因此TrueType字體得以作為標(biāo)準(zhǔn)字體,應(yīng)用如此廣泛。
2 ?TrueType字體分析
2.1 ?TrueType字體結(jié)構(gòu)
TrueType字體文件數(shù)據(jù)內(nèi)容由表頭、一系列描述表目錄和描述表組成,并由不同表中的數(shù)據(jù)組合起來(lái)描述字體中的每個(gè)字,其結(jié)構(gòu)如圖1所示。
2.2 ?表頭
TTF文件開(kāi)頭12字節(jié)為表頭(offset table),其內(nèi)容及數(shù)據(jù)類型如下(其中FIXED類型為帶符號(hào)整數(shù)小數(shù)各16位的32位定點(diǎn)實(shí)數(shù)):
FIXED ? ? version //文件版本號(hào)
USHORT ?numTables //描述表數(shù)目
USHORT ?searchRange //快速查找范圍
USHORT ?entrySelector //描述表入口
USHORT ?rangeShift //范圍調(diào)整
其中最重要的為numTables,其余項(xiàng)都可以由其計(jì)算得到,詳細(xì)信息可以參考TrueType說(shuō)明文件[2]。
2.3 ?描述表目錄
表頭(offset table)之后緊跟著描述表目錄,其個(gè)數(shù)為numTables個(gè),每個(gè)描述表目錄項(xiàng)都占有16個(gè)字節(jié),其結(jié)構(gòu)如下:
ULONG ?tag //描述表名稱
ULONG ?checksum //描述表校驗(yàn)和
ULONG ?offset //描述表偏移
ULONG ?length //描述表字節(jié)長(zhǎng)度
2.4 ?描述表
TrueType類型字體中包含的描述表最多可達(dá)到24個(gè),其中10個(gè)必須,14個(gè)可選,描述表目錄項(xiàng)按照表名字(tag)的升序排列。本文僅介紹10個(gè)必須的表,如下所示,可選表信息可參考TrueType說(shuō)明文件,且其不會(huì)影響字體裁剪。
cmap //字符代碼到文字序號(hào)映射表
glyf ? //字符輪廓信息表
head //字體文件頭信息表
hhea //水平度量頭信息表
hmtx //垂直尺寸信息表
loca //文字序號(hào)到位置索引信息表
maxp //最大值描述表
name //字體名表
post //PostScript信息
OS/2 //OS/2與Windows度量信息
10個(gè)表中與字體裁剪關(guān)聯(lián)較大的表有cmap、glyf、loca等三個(gè);head、hhex、hmtx、maxp、name等五個(gè)表也會(huì)有所涉及,下面對(duì)cmap、loca、glyf三個(gè)表進(jìn)行簡(jiǎn)要介紹。
2.4.1 ?cmap表
cmap表給出了字符由其本身編碼到字體中其序號(hào)的映射關(guān)系。譬如漢字“文”,其Unicode編碼為0x6587,根據(jù)這個(gè)編碼值通過(guò)cmap表便可以索引到“文”字在字體文件中的序號(hào),進(jìn)而可以根據(jù)字形輪廓繪制出“文”字。cmap表結(jié)構(gòu)如圖2所示。
表頭格式為:
USHORT ?cmap_version//cmap版本號(hào)
USHORT ?cmap_tables//cmap子表數(shù)
描述表目錄格式為:
USHORT ?Platform_ID
USHORT ?Platform_Encoding
ULONG ? Offset
描述子表有四種格式,分別對(duì)應(yīng)Format0、Format2、Format4、Format6,下面以Format4為例,簡(jiǎn)述輪廓信息查找過(guò)程。
Format4描述子表格式如下:
USHORT ?format//子表格式,此處為4
USHORT ?length//子表長(zhǎng)度(字節(jié)計(jì))
USHORT ?version//子表版本
USHORT ?segCountX2//子表分段數(shù)*2
USHORT ?searchRange//快速查找范圍
USHORT ?entrySelector//入口值范圍
USHORT ?rangeShift//偏移調(diào)整
//每段結(jié)束字符代碼
USHORT ?endCount[segCount]
USHORT ?reservedPad//保留對(duì)齊,為0
//每段開(kāi)始字符代碼
USHORT ?startCount[segCount]
//字符輪廓序號(hào)調(diào)整量
USHORT ?idDelta[segCount]
//每段映射子表所有字符輪廓序號(hào)存儲(chǔ)
//位置(在glyphIdArray數(shù)組中)相對(duì)
//當(dāng)前位置的偏移量
USHORT ?idRangeOffset[segCount]
//文字輪廓序號(hào)數(shù)組(變長(zhǎng))
USHORT ?glyphIdArray[]
其根據(jù)字符編碼查找字符輪廓索引(index)流程如圖3所示。
2.4.2 ?loca表
loca表記錄了每個(gè)文字的輪廓數(shù)據(jù)信息在glyf表中相對(duì)于glyf表初始位置的偏移,其依據(jù)cmap表中查詢到的字符索引,由該字符索引確定偏移位置,loca表結(jié)構(gòu)比較簡(jiǎn)單(其中char_index為字符輪廓索引):
USHORT offsets[char_index];
整個(gè)查詢過(guò)程如圖4所示。
2.4.3 ?glyf表
glyf表是TrueType文件中重要的表,其存儲(chǔ)了文字的輪廓描述信息,以及一系列的指令信息。glyf表較為復(fù)雜,不再將其表中變量一一說(shuō)明,具體說(shuō)明見(jiàn)TrueType文件。這里僅介紹簡(jiǎn)單及復(fù)雜字符輪廓的讀取過(guò)程如圖5所示。
3 ?軟件設(shè)計(jì)
為達(dá)到字體的定制功能,字體定制軟件要能夠讀取某一字體文件的內(nèi)容,對(duì)其進(jìn)行解析,根據(jù)需要對(duì)其裁剪,最后保存所需的部分,字體定制軟件結(jié)構(gòu)框圖如圖6所示。
字體定制軟件主要由兩個(gè)模塊組成:字體文件讀取模塊、字體子集定制模塊,軟件采用基于MFC架構(gòu)的C++語(yǔ)言開(kāi)發(fā)[3]。
考慮到TTF文件中表數(shù)的眾多,如果對(duì)每個(gè)表分別進(jìn)行獨(dú)立操作,將會(huì)使軟件的工程量變得很大,同時(shí)結(jié)構(gòu)還會(huì)變得相當(dāng)松散,這是比較差的設(shè)計(jì)方式。考慮到實(shí)際過(guò)程中并不需要對(duì)所有的表都進(jìn)行修改,并且利用C++語(yǔ)言的繼承和多態(tài)的特性,可以將對(duì)描述表的讀取通過(guò)以下方式實(shí)現(xiàn)。
所有的描述表都需要實(shí)現(xiàn)內(nèi)容讀取、內(nèi)容保存的功能,具有一定的共性,所以可以設(shè)計(jì)一個(gè)基類CTaleInfo類,而具體的每個(gè)表都可以從CTableInfo類進(jìn)行派生,如圖7所示。
類的定義如下所示:
Class CTableInfo
{
public:
//保存表信息
virtual void SetSave();
//從硬盤(pán)讀取文件
virtual void Load();
//將表信息寫(xiě)入文件
virtual void Store() const;
//將信息附加到表中
virtual void AppendGlyfByDoc(){};
//復(fù)制表信息
virtual void Duplicate();
//設(shè)置表對(duì)應(yīng)的TTF文件類
virtual void SetTtfDoc();
}
軟件界面如圖8所示。
4 ?結(jié) ?論
該軟件已經(jīng)開(kāi)始于工程中使用,其操作方便、運(yùn)用直觀,可對(duì)字體按需定制。經(jīng)過(guò)裁剪的文件大小適合于嵌入式系統(tǒng),大大提高了系統(tǒng)的運(yùn)行效率。
參考文獻(xiàn):
[1] 呂強(qiáng),史磊,楊季文.TrueType字體文件格式初探 [J].計(jì)算機(jī)研究與發(fā)展,1995(11):23-31+60.
[2] TrueType 1.0 Font Files,Technical Specification(Revision 1.66) [Z].Microsoft Corporation,1995.
[3] 孫鑫.VC++深入詳解(修訂版) [M].北京:電子工業(yè)出版社,2012.
作者簡(jiǎn)介:閆文奇(1988.10-),男,漢族,江蘇贛榆人,工程師,碩士,研究方向:控制器軟件開(kāi)發(fā)。