白鳳山,范道爾吉,金宇新,吳 威,張利宏
(內(nèi)蒙古大學 電子信息工程學院,內(nèi)蒙古 呼和浩特 010021)
在嵌入式Linux環(huán)境下處理蒙古文的技術(shù)還處于起步階段,這主要由于蒙古文不同于中、英文的語法和書寫特點,蒙古文要求豎直從上到下,從左到右排版。QTE是嵌入式Linux比較流行的圖形庫和中間件,也提供了基于Unicode的文字處理引擎,但QTE不支持蒙古文的豎排顯示和變形機制。蒙古文國際標準編碼字符集中只按蒙古文語音收入了抽象的蒙古文名義字符,包括傳統(tǒng)蒙古文的7個元音、27個輔音、11個標點符號、10個數(shù)字和4個控制字符[1]。同一個蒙古文字符的書寫(顯現(xiàn)形式)會根據(jù)其在詞語中的位置不同、單詞詞性等屬性不同而發(fā)生變化,即呈現(xiàn)在人們面前的是該字符變化后的形式(稱為顯現(xiàn)字符)。由于ISO/IEC 10646標準中沒有收入蒙古文顯現(xiàn)字符,因此在顯示蒙古文時需要將蒙古文的名義字符根據(jù)上下文聯(lián)系映射到其相應(yīng)的顯現(xiàn)字符,這對蒙古文的顯示處理帶來了很大困難。
蒙古文名義字符可以有多個顯現(xiàn)字形,例如一個蒙古文字符根據(jù)其在詞中的位置、詞的詞性和所處的音節(jié)有不同的顯現(xiàn)形式[2]。圖1顯示了蒙古文字符“o”(音)在獨立、詞首、詞中、詞尾時的七種字形顯現(xiàn)形式,字符和字形的關(guān)系不是一一對應(yīng)的,但是它在Unicode編碼表中只對應(yīng)一個編碼0x1825。此外Unicode編碼表中對蒙古文的變形顯現(xiàn)字符集沒有進行編碼。
圖1 蒙古文字符“o”(音)的7種顯現(xiàn)字形
蒙古文的變形規(guī)律非常復(fù)雜,并不是簡單的上中下的關(guān)系,會根據(jù)其在詞中位置、詞性、上下文等多方因素影響變形。因此使用常規(guī)文字處理方法并不能得到正確的蒙古文文字。在Windows Vista環(huán)境中使用了OpenType字體和復(fù)雜文本引擎(Uniscribe)后支持了蒙古文的變形和豎排顯示,但是QTE目前還沒有支持這種功能。
雖然QTE支持矢量字庫,但是嵌入式系統(tǒng)的運行環(huán)境有限,因此使用點陣字庫會得到更好的運行效果。Vista中微軟提供了Mongolian baiti字體,收錄了所有蒙古文的名義字符和顯現(xiàn)字符。我們可以從中提取一個自定義蒙古文字符集,共收入255個字符,包括35個名義字符和對應(yīng)的所有顯現(xiàn)字符,并給它們分配一個系統(tǒng)內(nèi)部碼(簡稱內(nèi)碼),內(nèi)碼只有局部意義,因此編碼可以任意分配。系統(tǒng)和外部交換信息時全部按標準Unicode編碼進行,只有顯示蒙古文時才把標準Unicode編碼轉(zhuǎn)換成內(nèi)碼,內(nèi)碼和Unicode之間通過算法可以互相轉(zhuǎn)換,點陣字庫中按內(nèi)碼順序存儲蒙古文字符的點陣信息。另外,由于蒙古文的字符高度不統(tǒng)一,因此需要每個字符的高度信息才可以正確繪制蒙古文,高度信息可以在制作蒙古文點陣時獲得并存儲成特定格式的文件和點陣字庫一起使用[3]。
本文提出的蒙古文顯示方法并沒有使用TrueType或OpenType等矢量文字的繪制機制,而是從底層的點繪制函數(shù)開始構(gòu)造自定義的蒙古文繪制函數(shù)。繪制時使用內(nèi)碼找到點陣信息開始位置,然后用點繪制方法繪制一個蒙古文字符。由于從底層開始繪制,因此很容易實現(xiàn)蒙古文字的豎排顯示[4]。
但是用戶輸入的蒙古文或從外部得到的蒙古文都是用蒙古文Unicode編碼表示的,因此再繪制蒙古文時先做預(yù)處理,把Unicode文字串變換成用內(nèi)碼表示的蒙古文,內(nèi)碼串再傳輸給繪制引擎進行蒙古文的顯示。
QTE采用了面向?qū)ο蟮木幊趟枷耄瑢⒉煌墓δ芊庋b在相應(yīng)的類中。QTE中有三個主要的基類:QObject、QApplication和QWidget,繼承關(guān)系如圖2 所示。QApplication類管理圖形用戶界面應(yīng)用程序的控制流和主要設(shè)置。QWidget類是所有用戶界面對象的基類。窗口部件是用戶界面的一個原子,它從窗口系統(tǒng)接收鼠標、鍵盤和其他事件,并且在屏幕上繪制自己的表現(xiàn)。QTE具有很強的擴展機制,從任何一個基類開始繼承后可以實現(xiàn)自定義類。
圖2 QTE類的繼承關(guān)系
從QFrame類繼承了一個新類叫做QMLabel,該類可以完成蒙古文的豎排顯示。從圖2可以看出QFrame是所有顯示編輯類的公共基類,因此從QFrame繼承是恰當?shù)摹Frame類提供一個虛函數(shù) drawContents,每次顯示屏幕需要刷新時都被調(diào)用。因此從QFrame類繼承的類必須實現(xiàn)自定義的drawContents函數(shù),這給我們提供了很大的靈活性。通過該函數(shù)各類可以實現(xiàn)不同形狀的窗口,也可以實現(xiàn)不同文字的繪制。drawContents函數(shù)形參是一個QPainter類,它是一個虛擬的繪畫類,提供一系列繪制函數(shù),比如drawPoint,drawLine,drawRect等等。QTE當中所有的顯示控件都包含QPainter類[5]。
通過QPainter繪制蒙古文的功能可以封裝的一個QMgl類,不從任何類繼承,定義如下:
#include
#define DOTSIZE 32 /*點陣大小32X32*/
#define MGLCOUNT 255/*符號個數(shù)*/
class Q_EXPORT QMgl
{
public:
QMgl();
int drawChar(QPainter *p,int code,int x,int y);
/*單個符號繪制*/
bool drawString(QPainter *p,QString str,int x,
int y); /*字符串繪制*/
int getHeight(int code); /*字符高度獲取*/
private:
char dianzhen[(DOTSIZE*DOTSIZE)/8*MGLCOUNT]; /*點陣信息數(shù)組*/
char charHeight[MGLCOUNT]; /*符號高度數(shù)組*/
bool openBinaryFile();/*讀取點陣文件*/
bool openHeightBinaryFile();/*讀取字符高度文件*/
QString mglconvert(QString str);/*蒙古文預(yù)處理函數(shù)*/
};
其中主要繪制蒙古文的函數(shù)是:
int drawChar(QPainter *p,int code,int x,int y);
P:QPainter類形參,邏輯繪制于實際的顯示設(shè)備對應(yīng),提供一系列繪制函數(shù)。
Code:蒙古文內(nèi)碼。
x、y:邏輯畫布上坐標,以像素為單位。
實現(xiàn)方法是通過code找到dianzhen中的起始位置,然后根據(jù)“0”或“1”判斷繪制點還是不繪制。這是整個文字引擎的最底層函數(shù),有了這個基礎(chǔ)函數(shù)后我們就可以利用它構(gòu)造功能更加強大的drawString函數(shù),處理自動換行、手動換行、滾動等問題。 drawString函數(shù)里首先應(yīng)該調(diào)用mglconvert進行蒙古文變形處理和Unicode到內(nèi)碼的編碼轉(zhuǎn)換,然后再調(diào)用drawChar進行字符的繪制。
QMLabel類的定義如下:
class QMLabel:public QFrame
{
Q_OBJECT
public:
QMLabel(QWidget * parent);
private:
QString Caption;/*顯示文字*/
QMgl *mgl;
void drawContents (QPainter * p);/*實現(xiàn)父類的虛函數(shù)*/
};
繪制函數(shù)的實現(xiàn)如下:
QMLabel::drawContents( QPainter * p){
mgl->drawString(p,Caption,left,top);/*繪制蒙古文*/
}
同理可以繼承一個QMEdit類,負責蒙古文的編輯功能,編輯也需要用顯示功能為基礎(chǔ),同時處理按鍵和鼠標等產(chǎn)生的事件,實現(xiàn)光標、文字增刪改、回車換行等功能。QTE下顯示蒙古文字效果如圖3。
圖3 QTE 下蒙古文字的顯示效果
通過上述方法繪制蒙古文字符之前需要進行預(yù)處理,把Unicode蒙古文串轉(zhuǎn)換成蒙古文內(nèi)碼串。預(yù)處理的基本思想是把Unicode文字串分解成一個一個Items項,每個Items可能是一個蒙古文文字,也可能是其他文字,通過Unicode編碼范圍判斷是不是蒙古文。再把每個蒙古文的Items通過一個變換函數(shù)處理,不是蒙古文的Items則不需要處理[6]。
變換函數(shù)需要對每個蒙古文名義字符進行處理,把它變換成正確的顯示形式并計算出對應(yīng)的內(nèi)碼。變形處理時需要考慮的因素有:
(1) 字符的位置:分獨立、上、中、下。
(2) 強制合體字:優(yōu)先考慮能否構(gòu)成強制合體字,同時考慮合體字的位置。
(3) 變形控制符:實現(xiàn)蒙古文編碼的變形控制符使用規(guī)則[7]。
(4) 上下字符關(guān)系:蒙古文的默認規(guī)則和特殊規(guī)則的對應(yīng),主要是在一個位置有多個候選顯示字時需要根據(jù)上下字符、詞性、讀音、特殊規(guī)則選擇正確的顯示字符,這需要對蒙古文的語法和構(gòu)詞方法進行詳細的總結(jié)和統(tǒng)計。
文中提供的QTE下蒙古文顯示機制是各類智能終端及便攜式手持顯示終端設(shè)備實現(xiàn)支持蒙古文顯示與控制比較理想的解決方案,經(jīng)過實踐證明也是可行的,為進一步開發(fā)支持蒙古文的嵌入式應(yīng)用產(chǎn)品提供了一種解決方法。
[1] 確精扎布.蒙古文編碼[M].呼和浩特:內(nèi)蒙古大學出版社,2000.
[2] 姚延棟,吳健,孫玉芳等.傳統(tǒng)蒙古文變形顯示機制研究與實現(xiàn)[J].中文信息學報,2005,18(5):84-89.
[3] S.蘇雅拉圖.傳統(tǒng)蒙古文整詞編碼研究[J].中文信息學報, 2001,15(2):57-64.
[4] 孟凡強,吳健,賈彥民.蒙古文顯示在OpenOffice.Org辦公套件中的實現(xiàn)[J].中文信息學報,2007,21(2):117-121.
[5] 周揚榮,賈彥民.復(fù)雜文本布局引擎機制及應(yīng)用研究[J].中國科學院研究生院學報,2006,23(3):390-395.
[6] 斯·勞格勞,敖其爾. Windows環(huán)境下蒙古文復(fù)雜文本處理的研究[J].內(nèi)蒙古大學學報,2007,38(5):582-585.
[7] 烏達巴拉,鞏政.蒙古文OpenType字體制作技術(shù)[J].內(nèi)蒙古大學學報,2006,37(5):570-573.