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
部分效果:

朝向

锚点

反向文本流

偏置

竖排

要做中文竖排/直书工具还有很多问题,比如标点。

评论