Why does tikz produce output in plain tex when it does not in latex?
Short answer:
\input tikz
loads the filetikz.tex
, while\usepackage{tikz}
loads the filetikz.sty
. Those files are different, and in turn load different files.- In particular,
pgfrcs.tex
has\input pgfutil-plain.def
whilepgfrcs.sty
has\input pgfutil-latex.def
- The code in
pgfutil-plain.def
has\openout
which results in the creation of a whatsit node (and hence “output”, and the DVI file), while the code inpgfutil-latex.def
piggybacks on LaTeX's aux file, which does\immediate\openout
instead.
How to isolate the issue
(This section just describes how the above was arrived at.)
This is what I tried. By looking in the log file (or using kpsewhich
), we can find the specific file that is being input, in the two cases. We can copy that file over to the current directory, and start editing it into something minimal: remove as much from it as possible, while the files still compile and exhibit the difference. They will probably input other files; copy them as well and repeat.
By doing this recursively, I was able to reduce the two cases to the following:
% 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.
where most of the files simply \input
the others as indicated in the log line above. The nontrivial files (after minimizing) are 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
Summary
The file pgfrcs.tex
has \input pgfutil-plain.def
while the file pgfrcs.sty
has \input pgfutil-latex.def
, and those two .def
files contain substantial differences.
In particular, in the plain TeX case, at minimum we're running the following:
\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
and that's already enough to result in the creation of the .dvi
file.
(The answer of @egreg explains the further contents of the .dvi
file—the PGF-related specials, that are needed to go into the PDF dictionary on every page—but not why a page is shipped out in the first place. To check this, we can simply remove the line \csname openout\endcsname\pgfutil@auxout\jobname.pgf
from pgfutil-plain.def
, and make absolutely no other changes, and see that your original testtex.tex
does not result in the creation of a DVI file, even though the stuff that @egreg showed is still present in pgfutil-plain.def
.)
What the above shows is that we can find the difference already between:
\input pgfsys
\end
(in plain TeX) and (in LaTeX):
\documentclass{article}
\usepackage{pgfsys}
\begin{document}
\end{document}
Also, here's an even more minimal plain-TeX file that results in the creation of a DVI file:
\newwrite\outfile
\openout\outfile\jobname.pgf
\end
In the LaTeX case (in pgfutil-latex.def
), there is a similar \AtBeginShipout
and everything, but there's no \openout
. Instead, it piggybacks on LaTeX's \@auxout
. That one is defined, in latex.ltx
(the definition of \document
), using \immediate\openout\@mainaux\jobname.aux
. And we can see that simply adding \immediate
to our earlier minimal file does not result in the creation of a DVI file:
\newwrite\outfile
\immediate\openout\outfile\jobname.pgf
\end
At some point, \pgfutil@abe
is executed, which issues \unhbox
.
Here's the justification:
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 }%