作者:王佑中 (
[email protected])
这一篇文章是这个系统的基础,这个系统的输出档是Postscript档。它可以使用中文Postscript字型,我们很幸运的有一套GPL的中文Postscript字型,本文就是介绍它的原理及安装使用。
本文中所提到的软体全部是GPL的软体,我对其中许多程序都加入修改,这些修改的程序在将来都会公开,目前在我只把执行档直接放在光盘上。你可以在光盘中的[[[!!!麻烦您填上正确的路径!!!]]]中拿到这些程序,并且如果你想知道原始程序的位置,请参考ORIGINAL这个文件。
目前UNIX上有许多套中文列印程序,基本上它们的输出档都是Postscript档。这是因为我们有一个最好的GPLPostscript档列印程序,它就是Ghsoscript。Ghostscript有绝佳的可移植性,它所支援的列印设备范围几乎包括了目前市面上所有可见的设备。而且它的品质就和高阶Postscript印表机一样好,甚至也完全支援彩色列印的功能。
所以在Linux的环境下所用Postscript做为输出档的格式是很自然的选择。但是要让Postscript档支援中文列印也不是一件很容易的事,原因是Postscript基本上所使用的字型格式中主要是为单位元组字集所设计。对於像中文这种双位元组的字集在当初设计时并未考虑,但因为Postscript语言是一种绘图语言,所以我们当然可以把中文当做图形来处理,不过Postscript所直接支援的一些文字列印功能就不能用了。
本文主要的目的是介绍一套在GPL下发行的中文Postscript字型,它完全可以在Ghostscript下运作,它的使用就和一般英文字型一样的容易。使用方法也完全一样,这实在要感谢杰胜公司的慷慨,使我们能有这一个字型可用。但很可惜的,可能几乎没有人知道如何在Linux下使用它,本书将打开它神秘的面纱。并在最後提出一个perlscript使大家可以使用它来列印简单的文字档。
不过我提醒各位,这里所提到的字型在目前附在Slackware内的Ghostscript并不能使用,因为它用了一些level2的功能(我猜)。请在使用前先安装3.33版以上的Ghostscript,我帮各位将它编译成gs333.tgz,这个文件也在光盘上可找到。不过其中并没有字型,请各位自己去把字型找来安装。(沿用2.61的字型也无不可,记得把Fontmap拷到/usr/lib/ghostscript/3.33中)
Jackson字型的安装
Jackson的中文Postscript字型可以在NCTUCCCA.EDU.TW://NeXT/Chinese/KaiSu.pkg_0_7.tar.gz中取得。但它没有辨法直接在Linux下列开,我把它解开後取出有用的部份并把它放在光盘中。
Jackson的字型分成二个档,一个是用来建立它的Postscript语言档,另一个是放字型定义的档。
KaiSu-Regular=====>字型定义档
KaiSu-Regular.dat=====>字型资料档
要把它放入Ghostscript内的步骤为
(1)将上述二个文件放入/usr/lib/ghostscript/fonts中。
(2)修改/usr/lib/ghostscript/Fontmap在最後加入/KaiSu-Regular(KaiSu-Regular); 不要忘了最後的分号。
(3)用下列文件测试它的功能。
你应该可以看到大大的观念篇叁个字。
#!
/KaiSu-Regularfindfont80scalefontsetfont100100moveto
(观念篇)show
showpage Jackson字型的原理
如果你只是单纯的想使用字型,那这一节就可以省略了。这一节是给那些对Jackson字型原理有兴趣,或想自己做其它Postscript字型的人看的。我们可以由TTF字型用和Jackson相同的方法产生字型。
下文中提到叁个程序都可在光盘上找到,它们的档名分别是CHPOST1.ps,CHPOST2.ps和CHPOST3.ps。你应该在看下文前先把它们印一份在手边参考。
由於在原先的Postscriptlevel1中,Postscript所提供的Type1和Type3字型均只适用於小於256字的字集。所以Postscript在level2中提供了额外的type0字型(注2),一般称为合成字(compositefont),它本身并没有有关字型的资料。相反的它是用来将多个不同的字型组合成一个字型,也就是说一个13095字的字集,须要52个字型才能装得下,我们可以使用一个type0字型来代表这些字型。更清楚的说,一个双位元组的字集有二个位元组,我们可以将第一个位元组看成字型码,第二个位元组看成字型索引。有兴趣的人可以在附录中找到一个对Postscript字型详细的说明,以下我们只针对Jackson字型如何由双位元组字串选到正确的字型定义的过程做说明。我假设你对Postscript组识字型的方法有一定了解,我尽量重复使用到的字型功能,如仍有不了解之处请参考附录或PostscriptLanguageReferenceManual。
首先我把KaiSu-Regular中的一小段程序码列出并在其中加上一些注解,我把它放在光盘中的CHPOST1.ps中。以%%!开头的注解是执行到该行时stack的状况(注1),它并不在原先的字型中。如果程序看不懂没关系,你可以直接由我後面的说明了解运作的过程。 注1:Postscript是一种堆叠导向的语言,它和forth有些类似,同样是采後序的运算式并将结果放在堆叠之上。 注2:在有些levelI的系统中也有这个延伸。
一个Jackson字型为一个Type0的字型,它被分为89个子字型。每一个子字型有158个字元,这刚好就是BIG5的编码方式。BIG5的第一码为0xa1-0xf9共59个不同的码,而其第二码为0x40-0x7e及0xa1-0xfe共158个不同的码。所以在Jackson中采取8/8的映射方式,上面的/bc就是每一个子字型中的BuildChar程序,这个程序是type3字型用来画字的程序,Postscript在呼叫这个程序之前会把字型字典和字型索引堆进堆叠之中,而这个程序在执行完後应把它们移出堆叠。
因为中文字集的字元数实在太多,我们不能如英文字集般把所有字元的定义都一次载入记忆体中。上面的程序就是用来做动态载入的动作,它只在实际用到时才去载入字型,不过这个程序还有可改进之处,我们可以把它每次载入的定义存在字型字典之中,如此当第二次用到时就不必每次去文件中载入字型定义了。
上面的程式还有一个可议之处,它放弃了字型快取(fontcache)的使用。这可能使程式的速度大受影响,我还不太明白它放弃的原因,也许要试过才知,不过在Ghostscript中速度似乎还可以接受。
我们接下来看一下子字型实际上的定义,由於每一个子字型除了Offsets以外都一样,我只列出第一位元是0xF9的字型为例。我把这部份程式放在CHPOST2.ps这个档案中。
它第一码是0xf9的字型定义,其它的也大致相同。它首先由CFT1JacksonFontdict中将各项字型资料拷贝过来,/DataFile就是字型资料档的名称,而/BuildChar就是指到前述的/bc中。值得注意的是最後一项/Offsets,它是一个长度为158*3的阵列,其中每一项就是相对字元在资料档中启始的位置。
至此我们已将所有Type3的字型准备好了,最後我们看一下KaiSu-Regular这个type0的字型如何把前面定义好的89个字型组合在一起,且了解一下Postscript解释器如何读入正确数目的字元。请参考CHPOST3.ps这个档案
在/KaiSu-Regular的定义中我们可以看到它的字元转译模式是6(注),这表示它使用SubsVector中的讯息来解释输入字串。它的SubsVector的定义为
/SubsVector<00802158>def
第1个00代表每次读入一个字元,後面叁个数字代表整个字型被分为四段,依次为第0-3号字型,然後由/Encoding中取出实际的字型编号,在这里就刚好是0-3,然後再由/FDepVector中取出实际的字型。上面的过程用意在分辨中文和英文的字型,如果把实际的字型范围列出。
0-0x7f第0号字型/_@ASCII
0x80-0xa0第1号字型/NotDefFont
0xa1-0xf9第2号字型/CFT1JacksonFontSupp
0xfa-0xff第3号字型/NotDefFont
这就是BIG5码的定义,在这个过程中只有合法的第一码实际取用到了Jackson字型,其馀的就用原先的字型。
所以一个中文字元被取出的过程如下,以0xa10x40为例
KaiSu-Regular看到0xa10x40,取出encoding为2,在/FDepVector中取得/CFT1JacksonFontSupp,这也是一个typ20字型。
/CFT1JacksonFontSupp是一个8/8mapping的type0字型,用0xa1为索引在/Encoding中取出0,故由/FDepVector中取得第一项/CFT1JacksonFontA1。
将CFT1JacksonFontA1堆入堆叠,并将0x40也推入堆叠,呼叫/BuildChar也就是前述的/bc
/bc由CFT1JacksonFontA1中的/Encoding取得0x40的索引为0,故由Offsets中取得档案的位置0,长度为9。
读入这个字元定义,这是一个type1的加密字元定义字串(encrypedcharstrings)。
做一个暂时的字型叫存在/CFT1JacksonFontTemp中,并造出一个字型,把前面读入的字元定义放在里面。
用一般show指令将这个临时产生的Type1字型中的字元印出。
看起来有些复杂,不过Ghostscript的速度还可以接受,且用的记忆体也还可接受。不过我有点怀疑它在DiplayPostscript时的速度。
如何由TTF字型转换而得到一个Postscript字型
看到这个标题很多人心跳加速吧!不过我先声明,我在这里只给你一个食谱而没有任何菜色。因为如同中文Postscript字型一样,我们并没有任何免费的TTF字型。所以我也不可能由任何TTF字型做Postscript字型给你,我只能告诉你方法,至於结果你必须自行去尝试了。而且这可能不是一件容易的事,你如果决定要自己一试,那你告检查一下你的配备是否足以胜任。
(1)当然一定要有至少一套的中文TTF字型。
(2)至少16MB最好有20MB以上的记忆体。
(3)至少50MB以上的硬碟空间,越大工作会越舒服,因为你不必把中间产生的档删除。 (4)很多很多的时间及很多很多的耐性
如果你准备好了,就跟着我开始上路吧!
由easyflow同一个子目录取得ttf2limn这支程式,它可以由TTF字型产生一个158字的pk字型档。用法为
ttf2limnntk5161.1440pkntk51611440161-s