Jade Dungeon

LaTeX CJK

加载过程

latex在运行过程中,明显的分成了几个阶段,每个阶段的字体定义并不一致。也就是, 站在不同的角度,定义是不同的。

编码映射到图像

我们首先要找到CJK宏包,将里面的宏展开,真正的字的图像(glyph)位置并不是一开始 就直接知道的,而是有一个过程,对于TEX来说,这个过程是字符的编码与字的图像建立 映射的过程。

\documentclass{article}
\usepackage{CJK}
\begin{CJK}{GBK}{song}
\begin{document}
您
\end{CJK}
\end{document}

第一步是把LaTeX编译为TeX,LaTeX发现用户使用了CJK宏包,所以从 \begin{CJK}{GBK}{song}\end{CJK}的内容里的中文都变成对应的TeX命令。 这些命令根据不同的汉字转换不同的字体。

例如:变成了\C19/song/m/n/10/51 s

  • (C19)表示用GBK编码的song体,
  • m表示粗细为medium(m), 而不是bold
  • n表示形状为upright(n), 而不是italic
  • 10代表大小是 10pt,
  • 51是子集号码.

因为C19song.fd里有这样一行:

\DeclareFontShape{C19}{song}{m}{n}{<-> CJK * gbksong}{}

所以\C19/song/m/n/10/51,会被C19song.fd这个字体描述文件映射为gbksong51。 对应的字体就是gbksong51 at 10pt(TeX术语)。

C19是NFSS编码,常用的有:

language environment NFSS encodeing
Chinese Bg5 C00
BG C10
... ...
Japanese JIS C40
... ...
Korean KS C60
... ...
Unicode UTF8 C70

从表里可以看到C19对应的是BG编码,如果要用UTF8的话,就要选择C70

\C19/song/m/n/10/51后面接着一个ss 的 ASCII 码是115, 正好是在这个 子集中的索引号。LaTeX 继续处理文档的其它部分,就象处理其它任何英语文件一样, 最后生成了 dvi 文件。

dvi转ps

第一步编码完生成了dvi,dvi要转换成ps。这时候字体定义又变了,对于dvi驱动来说, 字体的定义应该是:一个包含了字体图像(glyph)表示的的文件,这个文件可是是以 PK文件形式存储的位图文件(传统方式),也可以是一个更为现代的大纲(outline) 字体(PostScript或者True type)。

PostScript绘制字体

对于PS来说,字体就是包含着一些可以用来画字体图像的程序的文件,这些程序文件是以 PFA/PFB的编码形式存储的,这些程序可以通过标记名来访问,并且字体图像和字符的映射 是通过编码向量(encoding vectors)来实现的。

用户用dvips生成PostScript文件。dvips 找到config.ps配置,读取里面的字体映射文件 列表,列表里有一个文件叫做cjk.map, 它就去读取cjk.map

cjk.map指出gbksong51这个字体的图像(glyph)应该从Type1字体文件gbksong51.pfb 里得到。dvips把这些信息存到一张表里备用。dvips开始读取dvi文件,发现里面要求使用 gbksong51这个字体,并且输出一个s对应的字符。它就下载(download,PostScript 术语)gbksong51.pfb到生成的PostScript文件example.ps, 然后在合适的位置放上对 索引:s

打开example.ps就可以看到里面有如下内容:

%!FontType1-1.0: SimSun 2.10

...

TeXDict begin 1 0 bop 639 523 a Fb(s)1926 8991 y Fa(1)p
eop end

...

SimSun51就是所谓的PostScript字体名字,而(s)就是说输出字符串s显示为

对应UTF8编码的文档

如果要把编码从GB改为UTF8,对应的NFSS就要选择C70。 对应的文件是/usr/share/texmf/tex/latex/CJK/UTF8/c70gbsn.fd

\DeclareFontShape{C70}{gbsn}{m}{n}{<-> CJK * gbsnu}{\CJKnormal}
\DeclareFontShape{C70}{gbsn}{bx}{n}{<-> CJKb * gbsnu}{\CJKbold}

对应的*.map文件就是: /usr/share/texmf/fonts/map/dvips/arphic/gbsnu.map

gbsnu00 gbsnu00 <gbsnu00.pfb
gbsnu01 gbsnu01 <gbsnu01.pfb
gbsnu02 gbsnu02 <gbsnu02.pfb
...
gbsnufe gbsnufe <gbsnufe.pfb
gbsnuff gbsnuff <gbsnuff.pfb
gbsnuv gbsnuv <gbsnuv.pfb

常用字体与转换工具

常用字体:

  • traditional METAFONT bitmap fonts:
    • TFM,PL: TEX font metrics (binary format), property lists (textual format)
    • VF,VPL: virtual fonts (binary format), virtual property lists (textual format)
    • GF,PK: generic fonts, packed fonts (bitmap formats)
  • PostScript Type 1 outline fonts:
    • AFM: Adobe font metrics (textual format)
    • PFM: printer font metrics (binary format)
    • PFA: printer font ASCII (encoded glyph programs in textual format)
    • PFB: printer font binary (encoded glyph programs in binary format)
  • TrueType outline fonts:
    • TTF: TrueType font (includes both metrics and glyph programs)
    • T42: Type 42 font, TrueType font embedded in PostScript wrapper

常用转换工具:

  • TEXware /METAFONTware utilities:
    • tftopl,pltotf: convertTFMtoPLand back
    • vftovp,vptovf: convertVF/TFMtoVPLand back
    • gftopk,pktogf: convertGFtoPKand back
  • PostScript utilities:
    • afm2tfm(included withdvips): convert (and reencode) AFM to TFM
    • gsf2pk(included withxdvi): render PFA or PFB fonts to PK
    • t1binary,t1ascii(fromt1utils): convert PFA to PF Band back
    • t1disasm,t1asm(fromt1utils): decode or encode PFA or PFB
  • TrueType utilities:
    • ttf2afm(included withpdftex): generate AFM for TTF fonts
    • FreeType project:ttf2tfm,ttf2pk,ttf2pfb, etc.

安装UTF8编码可用的字体

sudo apt-get install fontforge

把字体文件(windows中常用的.ttf.ttc

mkdir tmp
cd tmp
cp simsun.ttc .
cp /usr/share/latex-cjk-common/utils/subfonts/* .
fontforge -script subfonts.pe simsun.ttc song Unicode.sfd

等几分钟,你回发现有大量的文件生成,其中就有tfm:



这就是前面看到gbsnu**类似的东西,一共有四种文件: .tfm.afm.pfb.enc

建立一个描述文件c70song.fd

% This is c70song.fd for CJK package.
% created by Edward G.J. Lee
% modify by Yue Wang
\ProvidesFile{c70song.fd}
\DeclareFontFamily{C70}{song}{\hyphenchar \font\m@ne}
\DeclareFontShape{C70}{song}{m}{n}{<-> CJK * song}{}
\DeclareFontShape{C70}{song}{bx}{n}{<-> CJKb * song}{\CJKbold}
\endinput

具体含义也非常简单,<->表示对任何字符都适用。

然后是通过写脚本mkmap.sh来建立映射文件,正如我们以前看的gbsu**的类似:

#!/bin/bash
for i in*.tfm
do
cat >> song.map << EOF
${i%.tfm} ${i%.tfm} < ${i%.tfm}.pfb
EOF
done

各种文件拷到特定的目录下,这种特定的目录结构(好像叫TSD目录结构)是方便编译器 按照规则找到对应的文件。不跟系统原来的混在一块,建议装在:/home/dev1/texmf下 在下面分别建立几个目录(实际是完全模仿gsbn的):

mkdir -p ~/texmf/fonts/map/dvips/CJK
mkdir -p ~/texmf/fonts/tfm/CJK/song
mkdir -p ~/texmf/fonts/type1/CJK/song
mkdir -p ~/texmf/tex/latex/CJK/UTF8

cp song.map ~/texmf/fonts/map/dvips/CJK
cp *.tfm ~/texmf/fonts/tfm/CJK/song
cp *.pfb ~/texmf/fonts/type1/CJK/song
cp c70song.fd ~/texmf/tex/latex/CJK/UTF8

sudo texhash
updmap -user --enable Map song.map