使用 up 和中文字体的纵书实(一

  • 1415
  • 9 min

目前使用 进行中文纵(亦称直书)排版主要有以下几个实现方法:

一、使用

主要思路是,首先将汉字向右旋转90度:

tex
\usepackage{fontspec}
\setCJKmainfont[RawFeature={vertical:+vert},BoldFont=SourceHanSerifCN-Bold.otf]{SourceHanSerifCN-Regular.otf}%CJK主字體。字體支持並直排。

然后对页面进行旋转:

tex
\usepackage{atbegshi}%打印.pdf時直放
\AtBeginShipout{\global\setbox\AtBeginShipoutBox\vbox{
        \special{pdf: put @thispage<</Rotate 90>>}
        \box\AtBeginShipoutBox}}

此种方法的优点是可以直接使用 兼容的宏包,对于字体、字体fallback、页边距的设定配置相对比较简单。对于“割注”可以使用李清、张瑞熹的gezhu包实现。
此种方法的主要问题是对于文中不同位置的标点的压缩方式设定不够灵活。
另外, 的宏包,比如fancy等,是基于横排设计的,设置页码、书名、章节名称等内容时,逻辑复杂。
因为此种方法局限性太大,笔者未进一步尝试。

二、使用 Lua

主要思路是使用 LuaTeX-ja 宏包实现中文直书。

2019年,Luigi Scarso等LuaTeX添加了HarfTEX,HarfBuzz库的支持,构建了另一个名为 Lua 的分https://www.tug.org/TUGboat/tb40-3/tb126devfund.pdf 32.)。从texlive2020开始,将LuaHBTeX作为 Lua 的默认引擎,提升了排版阿拉伯文、梵文等复杂文字的能力。
LuaTeX-ja是一个宏包,用于使用 Lua 排版日语文本。该项目的目标是为ASCII p 提供相同或好的排版方案,ASCII pTeX是传统的标准日本 引擎。

这种方法的优点是可以使用原生支持纵书的LuaTeX-ja、luatexja-fontspec、luatexja-otf等宏包,假话了字体的配置。
缺点是,第一次运行时,速度极慢。另外现在 Lua 还不够成熟,在展开一些字符空间比较大的字(比如sourcehans等)时,容易崩溃。
使用luatexja-otf宏包的UTF命令时,从UTF{F0000} 开始,取出的字形和实际码位不一致。

三、使用 up

p的日语版本,运行在 p上。 (带有日语排版扩展的 引擎。)
使用ptex进行日文纵书的文献可以追溯到1990年。
upLaTeX 是 p(日语 )的 Unicode 版本, 它运行在 up(具有更好Unicode支持的pTeX变体)上。
一个简单的例子如下:

tex
% !Tex=uplatex % 

\documentclass{utbook}

% 字体设置开始 %
\DeclareFontFamily{JY2}{sourcehanrm}{}
\DeclareFontFamily{JT2}{sourcehanrm}{}
\DeclareFontShape{JY2}{sourcehanrm}{m}{n}{<->s*[0.962216]upschrm-h}{}
\DeclareFontShape{JT2}{sourcehanrm}{m}{n}{<->s*[0.962216]upschrm-v}{}

\AtBeginDvi{
\special{pdf:mapline upstsl-h unicode SourceHanSerifSC-Regular.otf}
\special{pdf:mapline upstsl-v unicode SourceHanSerifSC-Regular.otf -w 1}
}
\DeclareRobustCommand\sourcehanrm{\kanjifamily{sourcehanrm}\selectfont}
% 字体设置结束 %

\usepackage{pxrubrica}%八登崇之的ruby包%
\rubysetup{g}% group%

\usepackage[uplatex]{otf} 

\begin{document}
\sourcehanrm

00平面:開,灰。
\par
02平面:𠀀,𪘀。
\par
15平面:\UTF{F0000},\UTF{F0001}。

\end{document}

运行:

sh
 ptex2pdf test1 -u -l

从这个最简单的例子可以看出,02平面和15平面的汉字无法显示。

查看生成的dvi文件:

sh
 updvitype test1.dvi
Font 50: upschrm-v scaled 962 (JFM tate)---loaded at size 630600 DVI units

 uplatex test1
 dvipdfmx -v  test1

><upschrm-v@9.59pt(TFM:upschrm-v)(VF:upschrm-v(TFM:upstsl-v)<upstsl-v@9.59pt
otf_cmap>> Creating Unicode charmap for font="SourceHanSerifSC-Regular.otf" layout="none"
(CID:SourceHanSerifSC-Regular)
pdf_font>> Type0 font "SourceHanSerifSC-Regular.otf" cmap_id=<unicode,2> font_id=<upstsl-v,2>.
>)(VF)>

可以看出,第一级虚拟字体为 upschrm-v ,二级虚拟字体为:upstsl-v
检查一下 jvf 的引用关系:

sh
 jfmutil vfinfo upschrm-v.vf
0=upstsl-v

我们需要修改tfm和vf文件,使其通过映射到字符范围更广的字体。

因为UF0000、UF0001等PUA区的字符无法在电脑上直接显示。需要用 otf宏包使用\UTF或\CID命令直接调用。需要直接指定otf宏包对应的虚拟字体的映射关系,所以不在此处进行设置。

sh
 cp -r $(kpsewhich upschrm-h.tfm) upschrm-sourcehanrm-h.tfm
 cp -r $(kpsewhich upschrm-v.tfm) upschrm-sourcehanrm-v.tfm
 cp -r $(kpsewhich upschrm-h.vf) upschrm-sourcehanrm-h.vf
 cp -r $(kpsewhich upschrm-v.vf) upschrm-sourcehanrm-v.vf

反编译upschrm-sourcehanrm-v.vf:

sh
 jfmutil vf2zvp -u --lenient upschrm-sourcehanrm-v.vf
 jfmutil tfm2zpl -u --lenient upschrm-sourcehanrm-v.tfm

修改:upschrm-sourcehanrm-v.zvp
在CODESPACE节加入:

text
U20000 U2FA1D UF0000 UF0001

同时修改:

text
(MAPFONT D 0
   (FONTNAME upstsl00-v)
   (FONTCHECKSUM O 0)
   (FONTAT R 1.0)
   (FONTDSIZE R 10.0)
   )
(MAPFONT D 6
   (FONTNAME upstsl02-v)
   (FONTCHECKSUM O 0)
   (FONTAT R 1.0)
   (FONTDSIZE R 10.0)
   )
(MAPFONT D 7
   (FONTNAME upstsl15-v)
   (FONTCHECKSUM O 0)
   (FONTAT R 1.0)
   (FONTDSIZE R 10.0)
   )
……
(CHARACTER H 20000
   (MAP
      (SELECTFONT D 6)
      (SETCHAR )
      )
   )
(CHARACTER H 2FA1D
   (MAP
      (SELECTFONT D 6)
      (SETCHAR )
      )
   )
(CHARACTER H F0000
   (MAP
      (SELECTFONT D 7)
      (SETCHAR )
      )
   )
(CHARACTER H F0001
   (MAP
      (SELECTFONT D 7)
      (SETCHAR )
      )
   )

理论上讲,要对 “D 6” 、 “D 7” 组中的所有字符的unicode进行映射,这里针对示例,仅影射了 U20000、U2FA1D、F0000、F0001。
编译upschrm-sourcehanrm-v.zvp

sh
jfmutil zvp2vf -u --lenient upschrm-sourcehanrm-v.zvp

接下来复制 upstsl-v

sh
cp -r $(kpsewhich upstsl-h.tfm) upstsl00-h.tfm
cp -r $(kpsewhich upstsl-v.tfm) upstsl00-v.tfm

cp -r $(kpsewhich upstsl-h.tfm) upstsl02-h.tfm
cp -r $(kpsewhich upstsl-v.tfm) upstsl02-v.tfm

cp -r $(kpsewhich upstsl-h.tfm) upstsl15-h.tfm
cp -r $(kpsewhich upstsl-v.tfm) upstsl15-v.tfm

将代码修改为:

tex
% !Tex=uplatex
\NeedsTeXFormat{pLaTeX2e}
\documentclass{utbook}

% 字体设置开始 %
\DeclareFontFamily{JY2}{sourcehanrm}{}
\DeclareFontFamily{JT2}{sourcehanrm}{}
\DeclareFontShape{JY2}{sourcehanrm}{m}{n}{<->s*[0.962216]upschrm-sourcehanrm-h}{}
\DeclareFontShape{JT2}{sourcehanrm}{m}{n}{<->s*[0.962216]upschrm-sourcehanrm-v}{}

\AtBeginDvi{
\special{pdf:mapline upstsl00-h unicode SourceHanSerifSC-Regular.otf}%
\special{pdf:mapline upstsl00-v unicode SourceHanSerifSC-Regular.otf -w 1}%

\special{pdf:mapline upstsl02-h unicode FZSJSONG02.TTF}
\special{pdf:mapline upstsl02-v unicode FZSJSONG02.TTF -w 1}

\special{pdf:mapline upstsl15-h unicode FZSJSONG15.TTF}
\special{pdf:mapline upstsl15-v unicode FZSJSONG15.TTF -w 1}

\special{pdf:mapline utfjmr--v  unicode FZSJSONG15.TTF -w 1} % 使用CID/UTF命令调用
}
\DeclareRobustCommand\sourcehanrm{\kanjifamily{sourcehanrm}\selectfont}
% 字体设置结束 %

\usepackage{pxrubrica}%八登崇之的ruby包
\rubysetup{g}% group && head


\usepackage[uplatex]{otf} 

\begin{document}
\sourcehanrm

00平面:開,灰。
\par
02平面:𠀀,𪘀。
\par
15平面:\UTF{F0000},\UTF{F0001}。

\end{document}

运行:

sh
 ptex2pdf test1 -u -l

从这个最简单的例子可以看出,02平面和15平面的汉字的显示正常了。