这个例子

这个例子

我正在完成一份文件。有几个未满的垂直框,我就是搞不清楚它们在哪里。有时很容易从日志文件中找出哪个页面未满的垂直框,但有时却不那么容易。有没有简单的方法可以可视化未满的垂直框,就像可视化过满的水平框的小条一样?

答案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 处理logtex 生成的文件,并搜索“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

不,您只能使用日志文件中的消息。

相关内容