Open tanukihee opened 2 years ago
嗯,我也在想这个问题,方法应该还是有的:https://tex.stackexchange.com/a/451951/179770,不过目前还没有仔细研究过这个代码。主要是不懂 METAFONT/MetaPost,得从头研究一下怎么工作的。
代码方面基本研究明白了,先写个草稿,
\documentclass[tate]{jlreq}
\usepackage{luacode}
\begin{luacode*}
-- adapted from https://tex.stackexchange.com/a/451951
-- We need some utilities from ConTeXt
callbacks = callbacks or {}
callbacks.supported = callbacks.supported or {}
dofile(kpse.find_file("util-fmt.lua"))
dofile(kpse.find_file("node-ini.lua"))
dofile(kpse.find_file("font-mps.lua"))
-- dofile(kpse.find_file("font-shp.lua")) -- unnecessary on current TeX version
-- That's a simple REImplemetation of ConTeXt's \showshape macro
function outlinejfontpaths(character)
local fontid = font.current()
-- prioritise using tate luatexja font
local curjfnt = tex.getattribute('ltj@curjfnt')
local curtfnt = tex.getattribute('ltj@curtfnt')
if curjfnt >= 0 then
fontid = curjfnt
end
if curtfnt >= 0 then
fontid = curtfnt
end
local shapedata = fonts.hashes.shapes[fontid] -- by index
local chardata = fonts.hashes.characters[fontid] -- by unicode
local shapeglyphs = shapedata.glyphs or { }
character = utf.byte(character)
local c = chardata[character]
if c then
if not c.index then
return {}
end
local glyph = shapeglyphs[c.index]
if glyph and (glyph.segments or glyph.sequence) then
local units = shapedata.units or 1000
local factor = 100/units
local paths = fonts.metapost.paths(glyph,factor)
return paths
end
end
end
\end{luacode*}
\usepackage{luamplib}
\mplibsetformat{metafun}
\everymplib{beginfig(0);}
\everyendmplib{endfig;}
\edef\letterhash{\string#}
\def\mpdefineoutlines#1#2{\directlua{
local char = "\luaescapestring{#2}"
local outlines = outlinejfontpaths("#1")
local len = \letterhash outlines
tex.print("path " .. char .. "[];")
tex.print(char .. "n := " .. len .. ";")
for i, path in ipairs(outlines) do
tex.print(char .. "[" .. i .. "] := " .. path .. ";")
end
}}
\newbox\mympbox
\setbox\mympbox\hbox{
\begin{mplibcode}
pair shift; shift := (0pt,-27pt);
\mpdefineoutlines{一}{ICHI}
\mpdefineoutlines{レ}{REI}
path r;
numeric n; n := 0;
r := ICHI[1];
forever:
pair q;
r := r cutbefore (reverse REI[1] shifted (shift) );
exitif length cuttings = 0;
r := subpath(epsilon, length r) of r;
q = point 0 of r;
n := n + 1;
drawdot(q);
endfor;
\end{mplibcode}
}
\newcommand\countmp{\directlua{tex.sprint(node.length(tex.box.mympbox.head))}}
\begin{document}
\countmp
\end{document}
这样通过修改 shift 来测试移到什么地方可以使「一レ」刚刚接触,\countmp
输出 3 是不接触,4 是有接触,shift 的单位是 pt/100pt。metafont 好像没办法直接输出变量给 TeX,所以只能通过 box 这样 hack 一下。
排版方面,最简单的实现就是把刚刚好接触的「一レ」排出来,不过不知道是不是稍微重叠一些会更好……
https://github.com/edward-martyr/kanbun/pull/4
@tanukihee 请看一下这样符不符合要求,用 \usepackage[ichire]{kanbun}
开启自动调整「一レ」间距。
在某些字体下似乎会报错?
\documentclass{ltjtarticle}
\usepackage[match]{luatexja-fontspec}
\setmainjfont{Yu Gothic}
\usepackage[ichire]{kanbun}
\Kanbun
孤之有ルハ[二]孔明[一],猶ホ‹ごと›«キ»[二]魚之有ルガ[一レ]水也。
\EndKanbun
\begin{document}
\printkanbun
\end{document}
lualatex
(c:/texlive/2021/texmf-dist/tex/luatex/luamplib/luamplib.sty)[\directlua]:1: at
tempt to get length of a nil value (local 'outlines')
stack traceback:
[\directlua]:1: in main chunk
[C]: in function 'tex.runtoks'
c:/texlive/2021/texmf-dist/tex/luatex/luamplib/luamplib.lua:376: in upvalue 'r
un_tex_code'
c:/texlive/2021/texmf-dist/tex/luatex/luamplib/luamplib.lua:678: in field 'pro
cess_mplibcode'
[\directlua]:1: in main chunk.
\mpdefineoutlines ..."] := " .. path .. ";") end }
l.112 }
嗯,而且我测试下来好像就是系统自带的字体会出问题……
感觉也没有什么好方法?也没有类似于 xe 那样的获取 glyph 边界的命令,顶多加个选项控制 trim 的比例?