ConTeXt LMTX中文竖排思路
欢迎加入本人建的"LuaTeX ConTeXt 学习互助"群:431714622,互助学习LuaTeX ConTeXt LaTeX相关技术,以及通过Lua、Python实现格式化文本、数据的自动排版。
根据vertical-typesetting-in-context-mkiv这个答问中的线索学习了Hans Hagen所写的开发文档followingup的第6节:Directions(方向)。
感觉ConTeXt LMTX(LuaMetaTeX)很强大,安装说明;据说2022版TeX live要换上。
以下主要是从文档中拷贝的代码,有些地方做了注释,更正了个别笔误。
% \setuppapersize[A4][A4]
% \setuplayout[
% backspace=20mm,
% width=160mm,
% topspace=20mm,
% header=0mm,
% footer=0mm,
% height=250mm
% ]
% 根据 https://wiki.contextgarden.net/Chinese_Japanese_and_Korean
\mainlanguage[cn]
\language[cn]
\enableregime[utf]
\setscript[hanzi] % hyphenation
% 启用字体
\usetypescriptfile[mscore]
% \setupbodyfont [mschinese-literate,12pt]
\usebodyfont [mschinese,12pt]
% \usebodyfont [mschinese-light,12pt]
% \usebodyfont [mschinese-literate,12pt]
% \definebodyfontenvironment[24pt]
% \definebodyfontenvironment[18pt]
% \setuppagenumber [numberconversion=cn]
% \definestructureconversionset[chinese][numbers][cn]
% 章节序号
% \setupheads [sectionconversionset=chinese]
% \define[2]\ChineseChapter{第#1章 #2}
% \setuphead[chapter][command=\ChineseChapter,style={\bf\switchtobodyfont[24pt]}]
\setuphead[section][style={\bf\switchtobodyfont[18pt]}]
% \setuppagenumbering[state=start,
% alternative=singlesided,
% location={footer, center},
% style={\bf\switchtobodyfont[11pt]}
% ]
% \definefont[kaiti][name:kaiti*default at 24pt]
% \usemodule[zhspuncs]
% 行距
\setupinterlinespace[line=1.5em]
% 显式信息
\showboxes
% \showmakeup
\starttext
\section{朝向 orientation}
\subsection{使用与嵌套使用}
无朝向: This is a \LUAMETATEX\ goodie.
整体朝下: \hbox orientation 2{This is a \LUAMETATEX\ goodie.}
局部朝下: This is a \hbox orientation 2{\LUAMETATEX} goodie.
整体朝下、局部再朝下: \hbox orientation 2{This is a \hbox orientation 2{\LUAMETATEX} goodie.}
\subsection{6种朝向}
orientation 0—5:
\hbox orientation 0 {\TEX} and
\hbox orientation 1 {\TEX} and
\hbox orientation 2 {\TEX} and
\hbox orientation 3 {\TEX} and
\hbox orientation 4 {\TEX} and
\hbox orientation 5 {\TEX}
\subsection{锚点}
三位十六进制数表示的方向(前两位表示虚拟锚点):
0x<X><Y><O>
或TEX式:
"<X><Y><O>
X0-3分别表示如何水平对齐原空间边界: center, left(左外), right(右外), halfway left(左中) and halfway right(右中):
\hbox orientation "002 {\TEX} and
\hbox orientation "102 {\TEX} and
\hbox orientation "202 {\TEX} and
\hbox orientation "302 {\TEX} and
\hbox orientation "402 {\TEX}
Y0-3分别表示如何垂直对齐原基线: baseline, lower corner, upper corner or center:
\hbox orientation "002 {\TEX} and
\hbox orientation "012 {\TEX} and
\hbox orientation "022 {\TEX} and
\hbox orientation "032 {\TEX}
\page
\subsection{反向文本流}
两种方法,
一、指定盒子的流向为反向`direction 1`(\string\vbox同样可用):
\hbox{\hbox
orientation 0
direction 1
{朱泙漫学屠龙于支离益,殚千金之家,三年技成,而无所用其巧。} }
二、使用命令`\string\righttoleft`:
\hbox{\hbox
orientation 0
direction 0
{\righttoleft 朱泙漫学屠龙于支离益,殚千金之家,三年技成,而无所用其巧。} }
三、二者重复使用不会冲突:
\hbox{\hbox
orientation 0
direction 1
{\righttoleft 朱泙漫学屠龙于支离益,殚千金之家,三年技成,而无所用其巧。} }
\subsection{偏置}
\hbox{偏置 0x0}
\hbox
orientation 0
xoffset 150pt
yoffset 15pt
{偏置 150x15}
\vbox
orientation 0
{\hbox{\string\hbox\ 偏置 0x0}}
\vbox
orientation 0
xoffset 150pt
yoffset -15pt
{\hbox{\string\hbox\ 偏置 150x-15}}
\subsection{竖排/直书}
\startluacode
local glyph_id = node.id("glyph")
local fontdata = fonts.hashes.identifiers -- assumes generic font loader
--判断是不是汉族(是否需要直排)
local function is_vertical(c)
-- 常用的汉字编码范围,还有更多
return c >= 0x04E00 and c <= 0x09FFF
end
-- 处理程序,输入一个盒子号码
function document.go_vertical(boxnumber)
local box = tex.getbox(boxnumber)
local n = box.list
while n do
if n.id == glyph_id and is_vertical(n.char) then
local o = .2 * fontdata[n.font].parameters.xheight
local prev, next = n.prev, n.next
n.next, n.prev = nil, nil
local l = nodes.new("hlist")
l.list = n
local w, h, d = n.width, n.height, n.depth
if prev then
prev.next, l.prev = l, prev
else
box.list = l
end
if next then
l.next, next.prev = next, l
end
l.width, l.height, l.depth = h + d + o, w, 0
l.orientation = 0x003
l.xoffset, l.yoffset = o/2, -o/2
l.hoffset, l.doffset = h, d - o
n = next
else
n = n.next
end
end
end
\stopluacode
% 调整非中文的偏置
\unexpanded\def\stripe#1%
{\hbox orientation 0 yoffset .2\exheight{\strut #1}}
% 生成一个横向盒子(测试材料)
\newbox\MyVerticalBox
\setbox\MyVerticalBox\hbox \bgroup
\startscript[hangul]%
\dorecurse{20}{%
朱泙漫学屠龙于支离益,殚千金之家,三年技成,而无所用其巧。%
\stripe{ test #1} }%
\unskip % remove last space
\stopscript
\egroup
% 处理盒子
\ctxlua{document.go_vertical(\number\MyVerticalBox)}
% 解开盒子重排在\ruledvbox
\ruledvbox orientation 1 to \textwidth \bgroup
% \setupinterlinespace[40pt]
\hsize .92\textheight
\unhbox\MyVerticalBox
\vfill
\egroup
% 还需要处理标点等问题
\stoptext
要做中文竖排/直书工具还有很多问题,比如标点。