为什么 tikz 在纯 tex 中产生输出而在 latex 中却没有?

为什么 tikz 在纯 tex 中产生输出而在 latex 中却没有?

这个简单的文档testlatex.tex

\documentclass{article}
\usepackage{tikz}
\begin{document}
\end{document}

运行时latex testlatex产生No pages of output.

但这份文件testtex.tex

\input tikz
\end

运行时tex testtex产生Output written on testtex.dvi (1 page, 3312 bytes).

我希望第二个也不会产生任何输出,为什么它们不同?

答案1

简短回答:

  • \input tikz加载文件tikz.tex,而\usepackage{tikz}加载文件tikz.sty。那些文件不同,依次加载不同的文件。
  • 尤其是,pgfrcs.tex\input pgfutil-plain.defpgfrcs.sty\input pgfutil-latex.def
  • 中的代码pgfutil-plain.def\openout导致创建一个 whatsit 节点(以及“输出”和 DVI 文件),而 中的代码则pgfutil-latex.def搭载在 LaTeX 的 aux 文件中,从而实现上述目的\immediate\openout

如何隔离问题

(本节仅描述如何得出上述结论。)

这是我尝试过的。通过查看日志文件(或使用kpsewhich),我们可以在两种情况下找到正在输入的特定文件。我们可以将该文件复制到当前目录,然后开始将其编辑为最精简的内容:删除尽可能多的内容,同时文件仍可编译并显示差异。它们可能会输入其他文件;复制它们并重复。

通过递归执行此操作,我能够将两种情况简化为以下情况:

% tex testtex.tex                        
This is TeX, Version 3.14159265 (TeX Live 2017) (preloaded format=tex)
(./testtex.tex (./tikz.tex (./pgf.tex (./pgfcore.tex (./pgfsys.tex (./pgfrcs.tex (./pgfutil-common.tex) (./pgfutil-plain.def)) (./pgfsys.code.tex))))) [1] )
Output written on testtex.dvi (1 page, 196 bytes).
Transcript written on testtex.log.

其中大多数文件只是\input其他文件,如上面的日志行所示。非平凡文件(最小化后)是pgfrcs.tex

\input pgfutil-common.tex
\input pgfutil-plain.def

pgfutil-common.tex

\catcode`\@=11\relax

% Which format is loaded?
\newif\ifpgfutil@format@is@latex
\newif\ifpgfutil@format@is@plain

\let\pgfutil@aux@read@hook=\relax

\newtoks\pgfutil@everybye

pgfutil-plain.def

\pgfutil@format@is@plaintrue

% The aux files, needed for reading back coordinates
\def\pgfutil@aux@read@hook{
  \csname newwrite\endcsname\pgfutil@auxout
  \csname openout\endcsname\pgfutil@auxout\jobname.pgf
}

pgfsys.code.tex

% Read aux file in plain and context mode:
\pgfutil@aux@read@hook

概括

文件pgfrcs.tex有,\input pgfutil-plain.def而文件pgfrcs.sty\input pgfutil-latex.def,这两个.def文件存在实质性的差异。

具体来说,在纯 TeX 情况下,我们至少运行以下命令:

\catcode`\@=11\relax

%%%%%%%%%% From pgfutil-plain.def < pgfrcs.tex < pgfsys.tex < pgfcore.tex < pgf.tex < tikz.tex
% The aux files, needed for reading back coordinates
\def\pgfutil@aux@read@hook{
  \csname newwrite\endcsname\pgfutil@auxout
  \csname openout\endcsname\pgfutil@auxout\jobname.pgf
}

%%%%%%%%%% From pgfsys.code.tex < pgfsys.tex < pgfcore.tex < pgf.tex < tikz.tex
\pgfutil@aux@read@hook

\end

这已经足以导致.dvi文件的创建。

(@egreg 的回答解释了.dvi文件的进一步内容 - 与 PGF 相关的特殊内容,这些内容需要进入每一页的 PDF 词典 - 但并没有解释为什么首先要发送一页。为了检查这一点,我们可以简单地从中删除该行\csname openout\endcsname\pgfutil@auxout\jobname.pgfpgfutil-plain.def并且不做任何其他更改,并看到您的原始文件testtex.tex不会导致创建 DVI 文件,即使@egreg 展示的内容仍然存在pgfutil-plain.def。)

以上显示我们已经可以发现以下之间的差异:

\input pgfsys
\end

(在纯 TeX 中)和(在 LaTeX 中):

\documentclass{article}
\usepackage{pgfsys}
\begin{document}
\end{document}

此外,这是一个更简单的纯 TeX 文件,可创建 DVI 文件:

\newwrite\outfile
\openout\outfile\jobname.pgf
\end

在 LaTeX 案例中(在 中pgfutil-latex.def),有一个类似的\AtBeginShipout和一切,但没有\openout。相反,它搭载了 LaTeX 的\@auxout。它是在latex.ltx( 的定义\document)中使用定义的\immediate\openout\@mainaux\jobname.aux。我们可以看到,简单地添加\immediate到我们之前的最小文件中并不会导致创建 DVI 文件:

\newwrite\outfile
\immediate\openout\outfile\jobname.pgf
\end

答案2

在某个时刻,\pgfutil@abe被执行,从而发出\unhbox

理由如下:

272 \AtBeginShipout{% 
273   \setbox\AtBeginShipoutBox=\vbox{% 
274     \setbox0=\hbox{% 
275       \begingroup   
276                 % the boxes \pgfutil@abe ("every page") and \pgfutil@abb ("current page")
277                 % are used to generate pdf objects / dictionaries which are
278                 % required for the graphics which are somewhere in the "real"
279                 % page content.
280                 % BUT: these pdf objects MUST NOT be affected by text layout
281                 % shifts! Consequently, we have to undo \hoffset and \voffset
282                 % (which are h/v shifts to the page layout).
283                 %
284                 % Note that this of importance for shadings. To be more
285                 % specific: try out shadings with standalone (which uses
286                 % \hoffset) and with xdvipdfmx (which appears to be more
287                 % fragile than pdflatex) - they break unless we undo \hoffset
288                 % and \voffset.
289                 \ifdim\hoffset=0pt \else \hskip-\hoffset\fi
290         \pgfutil@abe 
291         \unhbox\pgfutil@abb 
292         \pgfutil@abc 
293         \global\let\pgfutil@abc\pgfutil@empty 
294                 \ifdim\hoffset=0pt \else \hskip+\hoffset\fi
295       \endgroup 
296     }% 

相关内容