歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> Linux中文化之在XFree86窗口系統中實現對GB18030的支持(一)

Linux中文化之在XFree86窗口系統中實現對GB18030的支持(一)

日期:2017/2/27 9:48:46   编辑:更多Linux

  蘇哲 ([email protected])
  Turbo Linux公司軟件工程師
  GB18030 是最新的漢字編碼字符集國家標准, 向下兼容 GBK 和 GB2312 標准。本文將向您講述如何在 XFree86 窗口系統中實現對GB18030 標准的支持。
  1. 簡介
  1.1 GB18030 簡介
  GB18030 是最新的漢字編碼字符集國家標准, 向下兼容 GBK 和 GB2312 標准。 GB18030 編碼是一二四字節變長編碼。 一字節部分從 0x0~0x7F 與 ASCII 編碼兼容。 二字節部分, 首字節從 0x81~0xFE, 尾字節從 0x40~0x7E 以及 0x80~0xFE, 與 GBK標准基本兼容。 四字節部分, 第一字節從 0x81~0xFE, 第二字節從 0x30~0x39, 第三和第四字節的范圍和前兩個字節分別相同。 四字節部分覆蓋了從 0x0080 開始, 除去二字節部分已經覆蓋的所有 Unicode 3.1 碼位。 也就是說, GB18030 編碼在碼位空間上做到了與 Unicode 標准一一對應,這一點與 UTF-8 編碼類似。
  目前最新的 glibc 2.2.x 系列已經全面支持了 GB18030 Locale 和 GB18030 與 UCS-4 之間的編碼轉換, 也就是說在系統層上 Linux 已經可以支持 GB18030 標准了。 下面問題的關鍵就是怎樣讓 XFree86 窗口系統也支持 GB18030 標准。
  1.2 XFree86 國際化原理簡介。
  本文介紹的所有內容都基於 XFree86 4.0.3 及其以後版本, XFree86 早期版本未做測試。
  XFree86 窗口系統中涉及到國際化的部分主要有字體管理, 文字繪制, 編碼轉換以及進程間通訊。 具體的編程接口請參閱相關資料, 本文不作更詳細的介紹。
  1.2.1 字體管理與文字繪制
  早期的 XFree86 由於對國際化問題考慮不足, 在字庫接口上僅定義了單字節索引和雙字節索引兩種字庫接口, 分別對應 XDrawString 和 XDrawString16 兩組函數。 前一組函數使用8位字模索引序列, 後一組函數使用16位字模索引序列。 函數定義分別為:
  XDrawString(display, d, gc, x, y, string, length)
  Display *display;
  Drawable d;
  GC gc;
  int x, y;
  char *string;
  int length;
  XDrawString16(display, d, gc, x, y, string, length)
  Display *display;
  Drawable d;
  GC gc;
  int x, y;
  XChar2b *string;
  int length;
  注意, 兩個函數中的 string 指針指向的並不是編碼序列, 而是字模在字庫中的索引序列。一般將這個序列使用的編碼轉化成為字符集(CharSet)編碼。 對於 ISO8859-1 等8位編碼的西方語言來說, 編碼和字符集編碼是一樣的。 所以可以直接用 XDrawString 顯示顯示這些編碼的字符串。 但對於多字節編碼的復雜語言來說就不一樣了。 以 GB2312 為例, GB2312 編碼(encoding) 的范圍為單字節 0x00~0x80, 雙字節 0xA1A1~0xFEFE, 而 GB2312 字庫的字符集僅覆蓋 GB2312 編碼的雙字節部分, 其編碼是將 GB2312 雙字節編碼中每個字節的第8位置0得來的, 例如, GB2312 編碼為 0xA1A1 的字符的字模(glyph)信息在 GB2312 字庫中的索引是 0x2121, 而不是 0xA1A1。
  早期的 XFree86 系統並不支持 ttf 字體, 對於 XFree86 系統中常用的 BDF/PCF 點陣字體而言, 每種字體使用的字符集編碼是固定的, 如中文字庫有 GB2312.1980-0, GBK-0, BIG5-0 等字符集, 日文有 JISX0201。1976-0, JISX0208。1983-0 等字符集。 後來人們在 XFree86系統中引入了對 ttf 等矢量化字體的支持, 目前用於 XFree86 4.x 的 ttf 字庫模塊有 freetype 和 xtt。 由於絕大多數 ttf 字體都直接使用 UCS2-BE 作為字符集編碼(字庫索引)。 為了和現有 XFree86 系統兼容, 這兩個模塊都具備編碼轉換功能, 即可以將傳統的字符集編碼轉換為 UCS2-BE 編碼, 從而可以將 ttf 字庫虛擬成傳統的字庫來使用。 為了便於字庫管理, XFree86 引入了 XLFD (X Logical Font Discription) 機制來描述字體。 關於 XLFD 的詳悉介紹請參閱 XFree86 的相關文檔。
  為了增強 X 窗口系統對國際化的支持, 在 X11R5 版本中引進了一系列新的字符串繪制函數和字體集的概念。 簡單來說, 字體集就是將幾種不同字符集的字庫組合成一個覆蓋多個字符集的新字體。 例如將一個 ISO8859-1 的英文字庫和一個 GB2312.1980-0 的中文字庫組合成一個字體集, 就可以覆蓋 GB2312 編碼的所有字符了。
  支持國際化的字符串繪制函數主要分為兩類 XmbDrawString 和 XwcDrawString。 它們的定義為:
  void XmbDrawString(display, d, font_set, gc, x, y, string,
  num_bytes)
  Display *display;
  Drawable d;
  XFontSet font_set;
  GC gc;



  int x, y;
  char *string;
  int num_bytes;
  void XwcDrawString(display, d, font_set, gc, x, y, string,
  num_wchars)
  Display *display;
  Drawable d;
  XFontSet font_set;
  GC gc;
  int x, y;
  wchar_t *string;
  int num_wchars;
  前一類用於繪制多字節編碼的字符串, 後一類用於繪制寬字節編碼的字符串。 使用這兩個函數可以直接繪制當前系統語言編碼的多字節編碼字符串或者 wchar_t 類型的字符串。 但實際上這兩個函數還是將多字節字符串或寬字節字符串拆分並轉換成多段不同字符集的編碼串, 然後調用 XDrawString 或者 XDrawString16 來顯示。 所使用的字庫就是字體集中對應的字庫。
  例如使用 XmbDrawString 繪制 "ABC大家好" 這個GB2312編碼的多字節字符串, XmbDrawString 首先會把這個字符串拆分成兩部分, 一部分是 "ABC" 對應 ISO8859-1 字符集, 將用字體集中的 ISO8859-1 英文字庫來繪制; 另一部分是 "大家好" 對應 GB2312.1980-1 字符集, 將用字體集中的中文字庫來繪制。 然後會將這兩個字符串分別轉換為對應字符集的編碼, 轉換後的結果為 "ABC" (未變) 和 0x73 0x34 0x52 0x3C 0x43 0x3A (即 "大家好" 的 GB2312.1980-0 字符集編碼, 也就是字庫索引)。 然後 XmbDrawString 就會分別調用 XDrawString 和 XDrawString16 來顯示這兩個字符串。
  1.2.2 進程間通訊
  X 窗口系統的進程間通訊主要涉及到不同進程間的文字拷貝和粘貼, 不同進程間的數據通訊以及程序的數據輸入等方面。 由於 X 窗口系統為 Client/Server 結構的分布式網絡窗口系統, 為了在保證進程間通訊的網絡透明性和可恢復性的同時, 提供國際化支持, 在 X 窗口系統內部引入了復合文本編碼 (Compound Text)。 這個編碼其實是以 ISO-2022(一種早期的多語言編碼框架標准) 為基礎制定的。 它並不是一種真正意義上的編碼, 而僅是一個能將多種不同編碼的字符流組合成一個字符流的框架協議。 進程間在使用 Compound Text 通訊的時候可以將各種不同編碼的字符流匯集在一起然後再傳輸, 到達目的進程後再按照一定規則解碼成多個字符流進行處理。 簡單來說, Compound Text 就是利用不同的狀態字符串來標志各個編碼字符串的起止位置, 利用一種統一的編碼規則對字符串進行編碼, 以免引起歧義。
  Compound Text 標准中為 ISO8859, EUC-CN, EUC-JP 等許多常用編碼規定了標准的編碼規則和狀態字符串, 另外還定義了幾種擴展規則, 用於將更新的編碼溶入 Compound Text 標准。 Compound Text 標准過於復雜, 而且所能包含的編碼數量也很有限。 隨著 ISO10646/Unicode 標准的不斷發展和完善, X 系統已經開始逐步用 UTF-8 編碼替換 Compound Text。 為了保持與舊系統的兼容性, 在 XFree86 系統中 UTF-8 編碼的字符串可以用一種特殊的編碼規則編碼成 Compound Text。
  1.2.3 編碼轉換
  前面已經提到了很多種文字編碼和標准, 簡單總結如下:
  多字節/寬字節編碼 (Multibytes/Wide Char): 通俗的說, 多字節編碼就是外碼, 一般為可變長編碼, 主要用於信息存儲和交換; 寬字節編碼就是內碼, 為定長碼, 通常一個字符對應4個字節, 主要用於信息處理。 在 POSIX 標准中定義多字節編碼的數據類型為 char, 寬字節編碼的數據類型為 wchar_t。 在目前 linux 常用的 glibc 2.2.x 版本中, 使用 UCS-4 作為寬字節編碼, 並遵循 Unicode 標准 (最新的 glibc 2.2.4 已經完全支持 Unicode 3.1 標准)。 常見的多字節編碼有 UTF-8, ISO8859 系列, GB2312, GBK, EUC-JP 等。
  字符集 (charset): 即一系列字匯(glyphs)的有序組合。 字符集一般使用固定長度的編碼。 常見的字符集有 Unicode (它即定義了編碼的標准, 又定義了字符集的標准), ISO8859-1, GB2312.1980-0, GBK-0 等。
  復合文本編碼 (Compound Text): 是一種可以將多個不同編碼的字符流匯集在一起的編碼標准, 常用於 X 應用程序之間的進程通訊和文字輸入。
  既然有這麼多不同的編碼和標准, 那麼 X 系統就必須能夠正確的處理並轉換它們。 在 X 的底層采用了一種模塊化的機制來處理所有編碼的轉換與翻譯工作。 這些轉換模塊被直接編譯到了 X11 Library 中 (具體源代碼請參閱 XFree86 源碼中的 xc/lib/X11/lc* 等文件)。
  首先, 在 X11 Library (以下簡稱 libX11) 中為它所支持的編碼標准定義了標准名稱 (見 XlcPublic。h 文件):
  #define XlcNMultiByte "multiByte" /* 多字節編碼 */
  #define XlcNWideChar "wideChar" /* 寬字節編碼 */
  #define XlcNCompoundText "compoundText" /* 復合文本編碼 */
  #define XlcNString "string" /* 傳統字符串編碼, 即 ASCII 編碼 */
  #define XlcNUtf8String "utf8String" /* UTF-8 編碼 */
  #define XlcNCharSet "charSet" /* 字符集編碼 */
  #define XlcNCTCharSet "CTcharSet"
  #define XlcNFontCharSet "FontCharSet" /* 字庫使用的字符集編碼 */


  #define XlcNChar "char" /* 單個字符 */
  #define XlcNUcsChar "UCSchar" /* UCS-4 編碼的字符 */
  其中 XlcNCharSet 和 XlcNFontC



Copyright © Linux教程網 All Rights Reserved