重新使用外部 tikzpicture 总是会失败,原因不明

重新使用外部 tikzpicture 总是会失败,原因不明

此 MWE 的工作基于以下问题的答案:这个问题。但是,尝试在真实文档中实现相同的结果总是无法生成外部图像,通常会出现如下错误:! error: (file cache/image-name.pdf) (pdf inclusion): reading image failed

\includegraphicsmaybe命令应该在第一次传递时跳过不可用的图像,但有些东西试图在图像准备好之前读取它。是否可以修改该命令,使其永远不会在 TikZ 外部例程期间运行?从该命令中删除文件扩展名会导致图像永远不会被包含,但文档可以正确编译。

% arara: lualatex: { shell: true }
% arara: tikzmake: { options: ['-j1'] }
% arara: lualatex: { shell: true }
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize[prefix=cache/,shell escape=-enable-write18]
\tikzset{external/system call={lualatex \tikzexternalcheckshellescape --halt-on-error --interaction=errorstopmode -jobname "\image" "\texsource"}}
\tikzset{external/mode=list and make}
\tikzset{
  % Defines a custom style which generates BOTH, .pdf and .png export
  % but prefers the .png on inclusion.
  %
  % This style is not pre-defined, you may need to copy-paste and
  % adjust it.
  png export/.style={%
    external/system call/.add=%
      {}
      ; convert -density 300 -transparent white -transparent-color white "\image.pdf" "\image.png",
  },
  png images/.style={%
    external/system call/.add=%
      {}
      ; convert -density 300 -transparent white "\image.pdf" "\image.png",
    % Don't need this as we're keeping the PDF in the document
      /pgf/images/external info,
      /pgf/images/include external/.code={%
        \includegraphics
        [width=\pgfexternalwidth,height=\pgfexternalheight]
        {##1.png}%
      },
  }
}
\DeclareGraphicsExtensions{.pdf,.png,.jpg}
\tikzset{png export}
\tikzexternalize
\newcommand{\includegraphicsmaybe}[1]{\IfFileExists{#1}{\includegraphics{#1}}{File #1 is missing.}}
\begin{document}
\tikzsetnextfilename{trees}
\begin{tikzpicture} 
\node {root}
child {node {left}}
child {node {right}
child {node {child}}
child {node {child}}
};
\end{tikzpicture}

Then reuse the tree:

\includegraphicsmaybe{cache/trees.pdf}

\end{document}

答案1

当图像在文档的其他地方重复使用时,TikZ 外部运行会失败,因为\IfFileExists将返回 true — 它仅检查文件是否存在,而不检查文件是否有效。尽管lualatex此时不应该在文档的其他地方运行任何代码,但它确实会运行,因此我们需要一种方法来防止加载不完整的图像文件。

解决方案是修改外部化例程,以便在作业完成时输出文件,然后\includegraphicsmaybe在尝试输入图像之前搜索该文件。

\usetikzlibrary{external}
\tikzexternalize[prefix=cache/,shell escape=-enable-write18]
\tikzset{external/system call={lualatex \tikzexternalcheckshellescape --halt-on-error --interaction=errorstopmode -jobname "\image" "\texsource"}}
\tikzset{external/mode=list and make}
\tikzset{
  % Defines a custom style which generates BOTH, .pdf and .png export
  % but prefers the .png on inclusion.
  %
  % This style is not pre-defined, you may need to copy-paste and
  % adjust it.
  png export/.style={%
    external/system call/.add=%
      {}
      ; convert -density 300 -transparent white -transparent-color white "\image.pdf" "\image.png",
  },
  png images/.style={%
    external/system call/.add=%
      {}
      ; convert -density 300 -transparent white "\image.pdf" "\image.png",
      % Don't need this as we're keeping the PDF in the document
      /pgf/images/external info,
      /pgf/images/include external/.code={%
        \includegraphics
        [width=\pgfexternalwidth,height=\pgfexternalheight]
        {##1.png}%
      },
  }
}
% Checks that images are OK
\tikzset{
  external/system call/.add={cat "\image.ok" && rm "\image.ok"; }{ && date > "\image.ok"},
}
% Skip files that haven't been rendered yet
\newcommand{\includegraphicsmaybe}[1]{\IfFileExists{#1.ok}{\includegraphics{#1}}{File #1 is missing.}}

cat "\image.ok" && rm "\image.ok"调用在编译之前删除了状态文件,从而阻止任何\includegraphicsmaybe依赖于该文件的 s 在 TikZ make 阶段运行。我认为将日期输出到状态文件中很有用,但 YMMV。

相关内容