高解析度字形在計算機中的壓縮表示(三)

前面我們介紹了不規則筆畫的表示方法,至此大家對EP0095536專利「高壓縮率」的一大特點有了比較深刻的認識。接下來我們將介紹「輪廓加參數」中的參數部分,也就是規則筆畫的表示方法。

在開始這個話題之前,可能大家會疑惑:為什麼橫、折、豎畫不能也用輪廓方法來描述?

其實也不是不可以,而且有的時候必須這樣。例如「戔」里的兩筆橫是斜的,這時候就只能當作不規則筆畫去處理了。但是這只是比較罕見的情況。在一般情況下,橫畫是水平的,這時候既可以用輪廓方法表示,也可以用參數方法表示。那麼為什麼不用輪廓方法表示呢?

第一,這些筆畫一般都比較長,用輪廓方法描述,就要大量用到10b開頭的長矢量,一個這樣的矢量需要兩個位元組,如果長度達到了64格還要中間「搭橋」。再加上筆畫頭尾和轉折處的筆鋒,一個筆畫往往要用掉十幾位元組,甚至更多。

第二,這些筆畫的筆鋒,形狀是固定的。例如簡體書宋有7000多個字,但橫畫的收筆筆鋒(筆畫右端的三角形)總共只有6種(見上圖)。折畫的折筆筆鋒,根據筆畫粗細的不同,也只有二三十種。這樣算下來,一段同樣的筆鋒會在字型檔里出現幾百次,甚至上千次。這樣的數據冗餘會造成極大的浪費,在本專利誕生的那個年代是不可容忍的。

第三,也是最重要的,用輪廓方法描述這些規則筆畫,不利於縮放時字形的質量。因為字形還原裝置在縮放時根本不知道當前正在縮放的是什麼筆畫,就會不加選擇地對每個節點進行簡單的坐標變倍處理,由於四捨五入的原因,這個過程中會造成偏差,最後造成的結果就是本來粗細相同的兩個筆畫,縮放後粗細不一樣了,這對字形的質量是個致命的打擊。以後我們會在這一方面進行深入的分析。

漢字中規則筆畫占的比重有將近一半,控制好規則筆畫的粗細對於確保字形質量十分重要。在此之上,還要有更高的壓縮率,節約每個位元組還不夠,要節約到每個比特!如何才能做到這一點?規則筆畫的表示方法於是應運而生。

規則筆畫表示方法概要

  • 橫畫的控制位元組的最高比特為0,折畫最高兩比特為10b,豎畫為11b。
  • 筆鋒存儲在編碼筆段文件里,全部用小於8的短矢量來描述,但是把控制位元組都省掉了,只留下表示矢量的每個位元組。字形還原裝置將根據字型檔的種類和筆鋒編號找到索引項,然後算出偏移量和長度,就可以找到筆鋒的矢量段。
  • 常規、粗體宋體的橫畫、折畫的起筆筆鋒只有一種形狀,因此壓縮信息中用一個比特表示有或無即可。還原字形時將自動產生筆鋒。
  • 一般情況下,用於主要部件的筆鋒較大,編號較小。用於次要部件的筆鋒則反之。
  • 筆鋒編號為0通常表示沒有筆鋒,如「非」字左邊的三橫,它們的收筆筆鋒編號都是0。但折筆筆鋒和仿宋體橫畫的起筆、收筆筆鋒除外,因為它們是必須要有的。
  • 折畫、豎畫的末尾可以是收筆筆鋒,也可以是任意形狀的一段矢量,如鉤、彎鉤、長撇等等。遇到這種情況,將表示收筆筆鋒編號的每個比特全部置為1,然後用矢量描述,緊接在後面。這樣可以省去表示起點坐標的位元組。

下面開始依次介紹常規宋體、粗體宋體、仿宋體、等線體的各種規則筆畫的參數及其表示方法。

常規宋體、粗體宋體橫畫

typedef struct tagSH {ntinttX;t// 起點水平坐標ntinttY;t// 起點垂直坐標ntinttLn;t// 長度ntinttWd;t// 寬度ntBOOLtbBgFtr;t// 有無起筆筆鋒ntinttnEdFtr;t// 收筆筆鋒編號n}SONGTIHORZ;n

【說明】

  1. 當X小於64且Wd和bBgFtr均為默認值時,可以使用第一種形式。否則要使用第二種形式,需要多用一個位元組。Wd和bBgFtr的默認值根據字體的不同而不同,例如書宋默認有起筆筆鋒,而報宋沒有。
  2. 若Wd為00b只是表示最細的寬度,並不意味著寬度就是0。Wd要加上一定的增量才是橫畫的實際寬度,這個增量也是根據字體的不同而不同。其他規則筆畫同理。

【例】書宋簡體的「一」字。它有10個節點,但只用了短短3位元組。即使算上用於表示規則和不規則筆畫的分隔位元組40h和末尾的0,也只有6位元組位元組數比節點數還少。由此更可證明本專利具有高壓縮率的突出特點。

字形還原裝置將根據壓縮信息取得筆畫的各項參數。

這個橫畫使用了最大的1號筆鋒。取得筆鋒編號後,即在編碼筆段文件尋找該筆鋒的索引項。

每個索引項也是大端序WORD類型,其中偏移量佔13比特,長度佔3比特。

偏移量:(0x61F9&0x1FFF)<<1=0x3F2

長度:(0x61F9>>13)+1=4

計算出偏移量和長度後,即可找到該筆鋒。

常規宋體折畫

typedef struct tagSRT {ntinttX;t// 起點水平坐標ntinttY;t// 起點垂直坐標ntinttLnH;t// 水平部分長度ntinttLnV;t// 垂直部分長度ntinttWdH;t// 水平部分寬度ntinttWdV;t// 垂直部分寬度ntBOOLtbBgFtr;t// 有無起筆筆鋒ntinttnTnFtr;t// 折筆筆鋒編號ntinttSlntV;t// 垂直部分傾斜度ntinttnEdFtr;t// 收筆筆鋒編號n}SONGTIREGULARTURN;n

【說明】圖中右下角部位的實心點是參數的X、Y表示的起點,但並不是筆畫的首個節點。為了便於計算,首節點取緊接著它右邊的那個空心點。如果SlntV為0,則這兩個點重合。可見,筆畫的起點坐標和首個節點的坐標不一定相等。

常規宋體豎畫

typedef struct tagSRV {ntinttX;t// 起點水平坐標ntinttY;t// 起點垂直坐標ntinttLn;t// 長度ntinttWd;t// 寬度ntinttnBgFtr;t// 起筆筆鋒編號ntBOOLtbSlntR;t// 右側有無傾斜ntBOOLtbSlntL;t// 左側有無傾斜ntinttLnFlt;t// 平直部分長度ntinttnEdFtr;t// 收筆筆鋒編號n}SONGTIREGULARVERT;n

【說明】若左右兩側均沒有傾斜(即bSlntL和bSlntR都是FALSE),最後一位元組可以不要,標有*的一比特置為0。

【例】下圖展示了一個有2橫畫、2折畫、3豎畫和1不規則筆畫的書宋簡體「苟」字,有一折畫末尾帶有不規則形狀的矢量。共有103個節點、8個筆畫,但只佔用48位元組。大家可以根據前面已介紹過的知識,自己對照字形來分析壓縮信息。

未來幾篇文章我們將介紹粗體宋體、仿宋體和等線體的規則筆畫。


推薦閱讀:

OS X 標楷體 PostScript 名稱修正
這張海報上的字體漸變效果是如何實現的?
縱排黑體字型的黑馬──蒙納盈黑
有沒有一種字體能夠明顯區別數字6與9?
如何評價 Intel 新字體 Intel Clear?

TAG:字体 | 宋体 | 计算机 |