我正在完成一份文件。有几个未满的垂直框,我就是搞不清楚它们在哪里。有时很容易从日志文件中找出哪个页面未满的垂直框,但有时却不那么容易。有没有简单的方法可以可视化未满的垂直框,就像可视化过满的水平框的小条一样?
答案1
好吧,我找到了一种方法来显示 pdf 中未满的框。有了 luatex,没有什么是不可能的!
这个过程有点复杂,但它确实有效(至少在我的最小示例中如此)。但让我们先看看结果。这是我准备的一个小示例文档,它生成了几个 Underfull vboxes。
这个例子
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}
\usepackage{nopageno}
\parskip=3mm plus 1mm
\begin{document}
1--- \lipsum[11]
\noindent\vbox to 6cm{% This should cause underfull vbox
2--- \lipsum[48]\par
3--- \lipsum[66]
}
4-- \lipsum[75]
\begin{center}
\begin{tabular}{|c|c|}
\hline
\vbox to 1cm{% Another underfull vbox
\vskip 1mm
\hbox{Foo}
\vskip 2mm plus 1mm
\hbox{Bar}
}
& Foo bar \\
\hline
Foobar & \vbox{\hbox{Foo}\hbox{bar}}\\ % No underfull this time
\hline
\end{tabular}
\end{center}
5-- \lipsum[101]
\end{document}
标有 2 和 3 的段落排版太大,表格中的\vbox
第一个段落也是如此。lualatex 抱怨:\vbox
$ grep Underfull example.log
Underfull \vbox (badness 5802) detected at line 13
Underfull \vbox (badness 1019) detected at line 25
结果 pdf 显示第 2 段和第 3 段之间的距离太远,因为 TeX 必须拉伸\parskip
它们之间的距离以使它们填满\vbox
。
期望结果
现在,我在上面 tex 源代码的前言中添加一行:
\directlua{dofile("DetectUnderfull.lua")}
再次使用 进行编译后lualatex
,新的 pdf 以红色显示未满的垂直盒子:
怎么做的
我的第一个想法是从 lua 处理log
tex 生成的文件,并搜索“Underful vbox”消息,记下它们发生的行号,然后挂钩到回调中process_input_buffer
以在该行插入某种标记。我在尝试实现这种方法时遇到了一些问题,所以我寻求帮助。
最后,我确信这种方法是不可行的,因为 LuaTeX 不提供回调来获取写入日志的消息,此外,file.open
不能file.read
安全地从 lua 使用它来读取 toe log
文件,因为该文件是打开的并且 TeX 正在同时写入它。
所以我尝试了一种不同的方法。我挂接了vpack_filter
回调函数,当 TeX 有材料需要打包到垂直盒子中并且即将开始打包时,该函数会被调用。通过 lua,我有机会检查该盒子(实际上是组成它的节点列表)、抛出它、让它通过,或者通过插入、删除或更改节点来修改它,所有这些都在 TeX 开始实际打包之前完成。
因此,我调用这个函数来node.vpack
“模拟” TeX 即将执行的操作,并返回打包结果和 badness 值。因此,我可以读取这个 badness 并确定它是否是“未满的 vbox”(badness > 100)。在这种情况下,我通过插入节点来修改该列表,这些节点在开头“推送”红色并在结尾“弹出”红色。我从源代码中了解到 鸡化打包一些巧妙的技巧来实现这一点。
代码
DetectUnderfull.lua
这是文件的内容:
-- Code to change color borrowed and adapted from chickenize package
WHAT = node.id("whatsit")
COL = node.subtype("pdf_colorstack")
color_push = node.new(WHAT,COL)
color_pop = node.new(WHAT,COL)
color_push.stack = 0
color_pop.stack = 0
color_push.cmd = 1 -- replace cmd with command if using LuaTeX >= 0.76.0
color_pop.cmd = 2 -- replace cmd with command if using LuaTeX >= 0.76.0
function vertical_pack(h, grcode, tam, tipo, maxd)
local g, b
g,b = node.vpack(h, tam, tipo)
if (b>100) then
color_push.data="1 0 0 rg"
h = node.insert_before(h,h,node.copy(color_push))
h = node.insert_after(h,node.tail(h),node.copy(color_pop))
return h
end
return true
end
-- Install my filter into luatex callbacks
luatexbase.add_to_callback('vpack_filter', vertical_pack, 'vpack_filter')
更新:感谢 uli 发现 LuaTeX 0.76.0 的问题,并感谢 Paul Gessler 修复该问题。
答案2
不,您只能使用日志文件中的消息。