qt字型檔的移植(使其很好的顯示中文)

來源:互聯網
上載者:User

http://blog.chinaunix.net/u3/93893/showart_1928488.html

 qt字型檔的移植(使其很好的顯示中文)

1 如何定製字型檔(移植字型檔)
    需要將至少兩個檔案賦值到....lib/font目錄下
1. fontdir 檔案。這個是應用程式尋找當前系統中最合適自己需要的字型檔的索引;

2,需要的字型庫檔案,一般是多個。具體移植那一個,看你使用的字型檔是什麼了,。比如我現在的系統我就是移植的wenquanyi_12pt.bdf就可以了,當然這個比較大。你也可以用小點的。我的flash比較大呵呵,懶得折騰。
在程式中需要這樣設定:

 QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));

設定使用utf-8編碼也就是unicode編碼了,這樣在tr和string的都是unicode的編碼了,根據字型檔的索引就能對應相應的字元了。

然後設定字型:

//字型設定
     QFont font("wenquanyi",12,QFont::Bold); //使用wenquanyi字型
     this->setFont(font);

//這樣就設定了字型了,中文一般使用wenquanyi字型就可以了。很好的。

基礎知識介紹:

字元編碼
1、
字元必須編碼後才能被電腦處理。電腦使用的預設編碼方式就是電腦的內碼。早期的電腦使用7位的ASCII編碼,為了處理漢字,程式員設計了用於簡體中文的GB2312和用於繁體中文的big5。在這些編碼中,中文和英文可以統一的處理,區分中文編碼的方法是高位元組的最高位為不為0。GB內碼的儲存方式始終都是big endian,即高位在前。

2、
Unicode是一種字元編碼方法,它是由國際組織設計,可以容納全世界所有語言文字的編碼方案。Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱為UCS。UCS可以看作是"Unicode Character Set"的縮寫。
Unicode與GB碼不相容,只與ASCII相容。
UCS規定了怎麼用多個位元組表示各種文字。怎樣傳輸這些編碼,是由UTF(Unicode transforation format)規範規定的。常見的UTF規範包括UTF-8(就是以8位為單元對UCS進行編碼)、UT F-7、UTF-16。
UTF-*和Unicode是同類,就是在編碼方式上不同。首先UTF編碼後的大小是不一定,不像Unicode編碼後的大小是一樣的。

字型庫:
一般認為,一個漢字的編碼就對應著這樣的字形,這還是錯誤的。內碼對於字型檔來說,只是尋找字形的索引。如果換成另一個編碼通訊協定的字型,同一個字串就會呈現不同的字形,也就是亂碼。
隨著GUI的發展,字型檔逐漸轉向TTF.TTF字型檔的編碼通訊協定沒有UTF8的
由於工作需要把ttf字型轉換成qpf字型,牽扯到了qt的makeqpf工具的使用方法
先簡單說一下qt的字型支援
Qte可以支援以下四種形態的字型格式
TrueType (TTF)、Postscript Type(PFA/PFB)、Bitmap Distribution Format fonts(BDF)、Qt Prerendered Font(QPF)
Qt中不同字型是用Unicode來處理、轉換
因為Unicode(UTF16或者UTF8)最適合在任何人之間傳遞資訊,
至於TrueType(不知道是什麼東西,先唬著)的支援,目前Qte採用的是FreeType2 Livrary來顯示字型,可充分享受無段式anti-aliased顯示。
經過下午的查證:Truetype是由AppleComputer公司和Microsoft公司聯合提出的一種新型數學字形描述技術。他用數學函數描述字型輪廓外形,含有字形構造、顏色填充、數字描述函數、流程條件控制、珊格處理控制、附加提示控制等指令。TrueType採用幾何學中二次B樣條曲線及直線來描述字型的外形輪廓,其特點是:TrueType即可以作列印字型又可以做螢幕顯示;由於它是由指令對字形進行描述,因此它與解析度無關,輸出時總是按照印表機的解析度輸出。無論放大或縮小,字元總是光滑的,不會有鋸齒出現。但相對PostScript字型來說,其品質要差一些,特別是在文字太小時,就表現得不是很清楚
簡單 一下:
truetype,字型就是可以不變形放大的字型,標準的字型大約有三種。*.fon 、*.ttf 、*.ttc,你所問的就是*.ttf 、*.ttc是*.ttf的新標準。*.fon就是很久以前用的字型,dos下現windows還有少量,主要用在系統使用方面可以提高程式的執行效率

FreeType是一個免費的並且可以被移植的TrueType 字型檔引擎,可以應用於很多平台!

 

fontdir的簡介
下面是截取qtcore中預設的fontdir檔案中的中文字型檔部分
#Chinese character font from http://wqy.sourceforge.net/en
wenquanyi wenquanyi_12pt.bdf BDF n 50 120 u
wenquanyi wenquanyi_13pt.bdf BDF n 50 130 u
wenquanyi wenquanyi_15pt.bdf BDF n 50 150 u
wenquanyi wenquanyi_16pt.bdf BDF n 50 160 u
wenquanyi wenquanyi_12ptb.bdf BDF n 75 120 u
wenquanyi wenquanyi_13ptb.bdf BDF n 75 130 u
wenquanyi wenquanyi_15ptb.bdf BDF n 75 150 u
wenquanyi wenquanyi_16ptb.bdf BDF n 75 160 u

可以看到共有七列
第一列:字型的名字,就是你在設定字型的時候的字型的名字
第二列: (file)即具體的檔案名稱字
第三列: (renderer)字型的格式,有BDF,TTT,QPF等選擇.
第四列: n 表示iitalic,是否為斜體
第五列:weight, 50 = Nomal,75=Bold
第六列: size 120表示12pt
第七列flags 有三個選項:s   (smooth)
                              u   (unicode順序儲存)
                              a   (ascii 順序儲存,預設是Latin 1)。

    檔案中每行都標識一個特定的字型檔,每個段的含義是:第一列為name,第二列為file,第三列為renderer,相當於字型格式,所以有 BDF,TTT,QPF等選擇。第四列n表示iitalic,表示是否為斜體字。第五列表示weight,其中50表示Normal,75表示Bold。第六列表示size,例如:120表示12pt。第七列為flags,有下面三個選擇:s=smooth(anti-aliased)u =unicode range when saving (default is Latin 1 a = ASCII range when saving(default is Latin 1))
                                                         —— 摘自參考文獻[1]
    其中屬性file,renderer(BDF,TTF,QPF)和size特別要設定對,其它屬性問題不大。還要注意如果在該目錄下有QPF的檔案,系統只會使用QPF格式的檔案,而不會讀取其它格式的檔案,不管FONTDIR裡面的內容是什麼。如果有多個QPF檔案,應用程式按照大小,家族,黑體和斜體的順序尋找,即首先尋找大小和自己一樣的字型檔,大小無法區分唯一的字型檔的再看對應的家族,還是無法區分的再看是否黑體,是否斜體。可以參考PC上的字型檔索引檔案FONTDIR:
例如:
-cclib -song -medium -r -normal -jiantizi -16 -160 -75 -75 -c -160 -gb2312 1980 -0
其中,每個段的含義如下:
cclib:製造商
song:字型族,此處表示“宋體”字
medium:字權重(中等),還有bold(粗體)選項
r:傾斜,R(Roman),I(Italic),O(Oblique)
normal:字元集寬度,此外還有condensed,narrow,double
jiantizi:附加說明(此處意義為“簡體字”)
16:用像素衡量的寬度。
160:點數 10
75(1):水平解析度(dpi)
75(2):垂直解析度(dpi)
c:間距。c:square,m:fixed width,p:variable width
160:平均寬度(10*pixels)
gb2312.1980:註冊字元集,標準名
0:第0套,基本集
                                                      —— 摘自參考文獻[2]

1.2 幾種格式字型檔的簡介
    QT支援四種格式的字型檔(TTF,BDF,PFA/PFB,QPF)(見參考文獻[3]),但在產品中,如果直接使用,TTF或PFA/PFB。即讓應用程式在顯示的時候再計算點陣,最終的效果並不理想,會發現有些字大,有些字小,而且需要佔用非常多的FLASH和記憶體,速度也有點慢,所以我在此不想過多的介紹PFA/PFB。如果直接使用BDF,速度非常慢,而且需要佔用比較多的FLASH和記憶體;使用QPF,速度和佔用其它資源是最小的,因此我們最終的產品中採用QPF格式。下面我簡單介紹,TTF,BDF和QPF字型的結構,這樣就比較容易理解後面的轉換過程。

1.2.1  TTF字型
   TTF(TrueType Font)是Apple公司和Microsoft公司共同推出的字型檔格式,隨著Windows的流行,已經變成最常用的一種字型檔表示方式。TTF 字型已經成功用在Windows中文版產生漢字字型檔,此字型採用二次B樣條曲線來描述字元輪廓,對字元輪廓的上的點,按順時針方向從小到大編號,填充部分在其右邊。TTF檔案結構分成三個部分:檔案名稱(12Bytes),描述表目錄(每個16Bytes),描述表資料。
    對於每一個字,都有一個假想的矩形框,正常情況字是不會超出這個矩形框的,中文屬於象形字,不象英文,大小不一致,比如:英文中的f就可能會超出矩形框。微軟把矩形的高度稱為EM,實際字元的高度稱為BODY.矩形框最原始的座標系是矩形的中心為原點,但為了實際字型在列印和顯示的使用過程中的方便,通常將座標原點放在左下角,或中下。
    通常,在實際列印過程中,TTF字型是用像素來度量的,如何將矩形框中的字型轉成像素呢?有一個計算公式,執行個體如下:如果18個點的72點每英寸屏下有一個550的長度,矩形框內有2048個單位。那其像素為550*18*72/72/2048=4.83像素。顯然,每英寸裡的點取的越多,字就越逼真,同時這樣的儲存空間和計算的時間也就越多。在嵌入程式開發過程中,這往往是不可以接受的,因為嵌入式系統的硬體資源本來就很有限,如果真的這樣的話,在顯示過程會很慢。並且如果為了提高速度而減少每英寸中的點數,則字型失真的情況很嚴重。更加具體的關於,TTF字型的內容可見參考資料[3]。
    另外,在Windows下編程,Microsoft實現了讓使用者對字型操作處理具有透明性,有關字型結構定義見參考文獻[4]。

1.2.2 BDF字型
    BDF(Bitmap Distribution Format)是在X視窗系統中的一種表示位元影像字型的檔案格式。是X協會定義的一種標準,是ASCII檔案它由兩部分組成,一是表示字型整體屬性的檔案頭資訊;二是每一個字元專屬的屬性和位元影像資料。我以16*16的位元影像字型為例描述BDF字型檔格式。
STARTFONT2.1 /*後面跟一個版本號碼,指出該字型檔版本*/
COMMENT /*表示注釋*/
FONT -adobe -courier -bold -r -normal -16 -160 -75 -75 -m -160 -gb2312.1980 -0
/*表示字型名*/
SIZE 16 75 75 /*字元大小與在X,Y方向上的解析度*/
FONTBOUNDINGBOX 16 16 0 0 /*X方向上寬度與Y方向高度及x和Y方向上的位移*/
STARTPROPERTIES 16 /*設定字型的屬性項目數*/
FOUNDRY "Adobe" /*字型的製造廠家*/
FAMILY_NAME "Courier" /*字型的變種字型*/
WEIGHT_NAME "Bold" /*字型的印刷權*/
SLANT "R" /*字型字型的設計情況*/
SEWINDTH_NAME "Normal" /*字型的縮放因素*/
ADD_STYLE_NAME "" /*唯一的標識該字型,一般為空白*/
PIXEL_SIZE 16 /*依賴於裝置的字型尺寸*/
POINT_SIZE 160 /*設計字型的實際尺寸*/
RESOLUTION_X 75 /*設計字型的水平解析度*/
RESOLUTION_Y 75 /*設計字型的垂直解析度*/
SPACING "m" /*指出字元寬度是定長還是可變*/
AVERAGE_WIDTH 160 /*字型中所有字元的平均寬度*/
CHARSET_REGISTRY "gb2312.1980" /*字元集名*/
CHARSET_ENCODING "0" /*字元集編號*/
FONT_DESCENT 0 /*基準下的高度*/
FONT_ASCENT 16 /*基準上的高度*/
ENDPROPERTIES /*屬性項設定結束*/
CHAR 6775 /*字型檔中的字元數*/
STARTCHAR 啊 /*字元起始標誌及名稱*/
ENCODE 3021 /*X伺服器在存取該字元時使用的編碼。如漢字國標碼*/
SWIDTH 1000 0 /*X和Y方向上的邏輯寬度和高度*/
DWIDTH 16 0 /*字元在x和Y方向上的裝置單位寬度*/
BBX 16 16 0 0 /*字元邊界框的寬度,高度以及位移*/
BITMAP /*字元的位元影像的資訊起始標誌*/
0000 /*字元位元影像*/
04a0
……
0590
ENDCHAR /*字元結束標誌*/
STARTCHAR 阿 /*第二個字元開始*/
……
ENDFONT /*BDF字型檔結束標誌*/

1.2.3 QPF字型簡介
    QPF格式的字型檔是僅用於QT/Embedded的不可縮放的字型,在程式運行過程中,對TTF格式的字型,在第一次裝入使用時,都要以給定的字型大小進行處理;而對於BDF字型,當其使用時,所有字型都必須被處理;而對於QPF字型,均以相同格式的儲存。所以在字型顯示時,Qt只要讀取字型,做相應分析,然後顯示就完成了,這樣進一步減少了對RAM資源的浪費。QPF字型是基於UNICODE編碼的,這為QT/Embedded良好的可移植性奠定了基礎。有關QPF更詳細的資料可以查閱參考文獻[5]。

2 如何從TTF字型檔轉成QPF字型檔
2.1 把TTF轉換成BDF
    儘管不推薦使用TTF格式的字型檔,但由於TTF格式的字型檔可以轉換成任意大小的BDF字型檔,而可以找到的BDF字型檔都是固定大小的,因此在實際製作QPF字型檔時,還是需要TTF格式的字型檔。把TTF轉換成BDF的方法如下:
./ttf2bdf source.ttf -p yourSize -o destination.bdf
    即利用軟體ttf2bdf可以把源檔案source.ttf轉換成大小為yourSize的BDF格式的檔案destination.bdf。那在程式內部是如何?將TTF轉成BDF的呢?由2.2.1和2.2.2的介紹,並且查閱參考文獻[3],可以知道TTF的內部儲存結構。其中最核心的部分是 TTF檔案格式中的12個位元組的檔案表:表目錄按tag以升序排列。

Type Name Description
ULONG  tag 4位元組的標識
ULONG checkSum 表中的CheckSum
ULONG offset TrueType font檔案的起始位移量Offset
ULONG length 表長

    還有一個有關Offset表的資訊,包括版本號碼,表的數量,尋找範圍。入口選擇,轉換範圍。
    通過操作檔案表,將描述表中的資料取出來,按照BDF字型所定義的格式寫入,就可以產生對應的字型。比如,可以給出一小段c語言程式,此程式用於計算當前CheckSum的位置。
ULONG
CalcTableChecksum(ULONG *Table,ULONG Length)
{
ULONG Sum = 0L;
ULONG *Endptr=Table+((Length+3)& ~3)/sizeof(ULONG);
while(Table<EndPtr)
Sum += *Table++;
return Sum;
}
    利用此程式可以將每個字型的資訊分開,並將每個字型資訊從檔案中取出來,對每個字型進行操作。在從TTF轉到BDF過程中,僅通過使用WINDOW的函數是很不方便的,最方便的辦法是使用c語言對字型進行操作。我在此列出轉換過程中最重要的幾個值:PIXEL_SIZE,POINT_SIZE,RESOLUTION_X,RESOLUTION_Y,FONT_DESCENT,FONT_ASCENT,SWIDTH,DWIDTH,BBX。這些值決定著最後產生的BDF字型與TTF字型的失真度,因為TTF是可縮放的,而BDF是固定大小的,所以在轉換過程中一定會出現失真的情況。

2.2 對得到的BDF檔案進行調整
    由於從軟體xmbdfed裡得到的三個字型檔不符合系統的要求,因此需要手動對其進行一些調整,其它方法得到的BDF檔案不需要進行調整。
直接從xmbdfed裡得到的字型檔是按照GB2312-80.0進行編碼的,因此首先要將其轉換成符合UNICODE編碼,這需要用到我手動寫的一個程式 gb2unieode,把源檔案拷貝到gb2unicode程式的目錄下,將其名字改為hanzist24a.txt(程式的要求,也可以不改名字而修改程式裡源檔案的名字再重新編譯),然後運行./change之後,就完成了,因為QT中因現成的轉換函式可以調用,在此我不想多說關於用程式轉換的代碼。因為有一種更簡單的方法,即在Word中開啟GB字型檔。然後另存新檔UNICODE字型檔檔案就行了。
    等待該命令執行完後(注意需要的時間比較長),對所產生的檔案dest.txt進行排序,方法如下:把dest.txt的名字改為dest.bdf(只要尾碼名為bdf就行);然後運行軟體xmbdfed,用其開啟該檔案(xmbdfed只能直接開啟尾碼明為bdf的檔案),另存新檔 yourname.bdf即可。排完序後需要手
動修改處理yourname.bdf。
    由上面介紹的BDF字型格式,現在對轉換得到的BDF字型檔進行如下手工處理:先刪除行說明屬性預設的字元的行DEFAULT_CHAR 8481,因為從GB2312轉換成UNICODE後,編碼為8481的字元已經不存在了,如果不刪除該行,運行時會出現段錯誤。然後刪除那些存在於兩個 16號字型檔但在標準GB2312中沒有的一些字模。標準GB2312中有7445個字模,而兩個16字型檔有7612個字模,多出來的那部分在用 gb2unicode轉換的時候因為找不到相應的GB2312碼而沒有寫進dest.txt的字模開始行"STARTCHAR ****"。可以用xmbdfed開啟,如果出錯則說明還有一些不完整的字模,還需要手動刪除這些不完整的字模,如果可以正確開啟則說明目標檔案已經是正確的。(24號字型檔不存在這個問題,因此不需要進行本項操作。)最後從其它大小相同的.bdf檔案中拷貝編碼為20-7F(ASCII碼)和編碼為 FE54(分號;)的字模到目標檔案。

2.3 把TTF.BDF轉換成QPF
    從參考文獻[5]中可以知道QT提供的把TTF,BDF轉換成QPF的方法有兩種,一種是工具makeqpf,這個命令無論是在Pc機上還是在開發板上都沒有效果(但是QT的官方網站卻說是可以的,不知道為什麼,並且,也不是每個版本的QT都有makeqpf這個工具,還要說明的是,文獻[6]中說這個工具是可以的,不過我沒有實驗成功)。
    另一種是運行應用程式時加上選項-savefonts,如在開發板上運行應用程式的命令:./sulfur -qws -savefonts
    如果此時系統中/usr/qt/lib/fonts目錄下沒有QPF格式的字型檔而只有TTF或BDF格式的字型檔,對應的檔案fontdir中只保留要轉換的檔案的行,QT就會在運行時首先產生QPF格式的字型檔。儘管通過TTF字型也可以得到QPF字型,不過最好不要這樣做,因為失真太大。

3 總結
    經過本人對字型檔進行上述處理後,就可以在嵌入式開發板上顯示各種字型,只要找到給定TTF或BDF的字型檔,如果找不到BDF字型檔,可以找到字型檔,然後通過 TTF2BDF這個程式來得到BDF字型檔。這樣在開發板上可以顯示行書,楷書等字型,並且字型顯示也很正常,不會出現大小不一致的問題。但是,本人認為,由於這是嵌入式開發,儲存資源非常有限,如果能進一步將字型檔縮小,只留下程式中所要用的漢字組成的字型檔就好了,這是需要下一步研究的方向。

參考文獻:
[1] http://jserv.Sayya.org/qtopia/doe/qte.txt
[2] http://www.Linuxfans.org/nuke/modules.php?name=Forums&file= viewtopic&t=82950&highlight=fonts.dir
[3] Microsoft Corporation. TTF Technical Specification Revision 1.66 November 1995.
[4] Windows 2000編程核心技術精解[M].中國水利水電出版社,2001.
[5] http://doc.Trolltech.com/3.0/emb-fonts.html
[6] 黃敬群.Qt/Embedded中文處理實戰[M]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.