Tikz 和 ctable 不兼容,打印时出错

Tikz 和 ctable 不兼容,打印时出错

当我打印报告时出现错误:

此页面存在错误。Acrobat 可能无法正确显示该页面。请联系创建 PDF 文档的人员以更正此问题

经过大量调试,我发现这个 MWE 重现了这个问题。我在三台不同的电脑上试过,都出现了同样的错误。

\documentclass{standalone}          
\usepackage{tikz}
\usepackage{ctable}
\begin{document}
\begin{tikzpicture}
\filldraw[opacity=.5] (0,0) rectangle (1,1);
\end{tikzpicture}
\end{document}

加载 ctable 包时,图像发生了变化(不透明度消失),因此错误似乎来自 tikz 中 ctable 和 opacity 之间的不兼容性。只有在尝试打印时才会出现错误,在尝试打印之前请先使用 Acrobat。(打印到 PDF 文件或真实打印机)

我有以下版本的 tikz 和 ctable:

tikz.sty 2013/12/13 v3.0.0
ctable.sty 2014/04/25 v1.29

我怎样才能解决这个问题?


编辑:我发现了来自 ctable 的警告Transparency disabled: incompatible with tikz package,所以我猜测这种不兼容性可以解释第一个 MWE 中的错误。

然而,我继续挖掘并发现间谍库似乎也与 ctable 不兼容。

这是一个 MWE,在打印时(无论是打印到 pdf 文件还是打印到真正的打印机)都会产生同样的错误:

\documentclass{standalone}          
\usepackage{tikz}
\usetikzlibrary{spy}
\usepackage{ctable}
\begin{document}
\begin{tikzpicture}[spy using outlines={size=2cm,connect spies}]
\begin{scope}
\spy on (-3,.25) in node at (2,0);
\end{scope}
\end{tikzpicture}
\end{document}

使用 tikz + ctable 似乎存在严重问题,可以修复吗?

答案1

ctable加载包transparent。包transparenttikz都实现透明度。这需要访问页面资源,ExtGState即透明值的字典。不幸的是,LaTeX 格式完全忽视了 PDF 开发。管理全局资源是操作系统的主要任务,格式为 TeX speek。由于缺少资源管理器,这两个包都做了大多数包所做的事,它们认为自己是独立的,并将它们的内容添加到资源中,\pdfpageresources在本例中。

% PDF file without compression for easier reading/analyzing
\pdfobjcompresslevel=0
\pdfcompresslevel=0

\documentclass{standalone}
\usepackage{tikz}
\usepackage{transparent}
\begin{document}
\begin{tikzpicture}
\filldraw[opacity=.5] (0,0) rectangle (1,1);
\end{tikzpicture}
\end{document}

PDF 对象 4 包含Resources页面(重新格式化):

4 0 obj
<<
  /ColorSpace 3 0 R
  /Pattern 2 0 R
  /ExtGState 1 0 R % by TikZ, see next object
  /ExtGState <<    % by package transparent
    /TRP1 << /ca 1 /CA 1 >>
  >>
  /ProcSet [ /PDF ]
>>
endobj

1 0 obj
<<
  /[email protected] << /CA .5 >>
  /[email protected] << /ca .5 >>
>>
endobj

可以看出,字典Resources(对象 4)包含两个条目ExtGState,这是 PDF 规范所不允许的。现在由 PDF 阅读器来决定如何解决这个问题以及使用哪个条目。因此,PDF 是否适用于哪个程序/打印机完全是偶然的。如果在页面中使用了两个包的透明度,那么总会出错,因为无论如何都会ExtGState缺少其中一个。否则,PDF 查看器/打印机有 50% 的机会选择未使用的ExtGState并丢弃另一个。

如果你不需要ctable/的透明度transparent,那么你可以欺骗 LaTeX,让它认为 /transparent已经加载了:

\makeatletter
\@namedef{[email protected]}{}
\makeatother
\usepackage{ctable}

ctable可以提供关闭透明度的选项。

transparent使用包pgf的资源管理的补丁

transparent下面的补丁在包加载后应用。然后它pgf通过使用宏来与包协作\pgfutil@addresource@extgs,用于透明设置和透明度方法两个都可以使用包。

\documentclass{standalone}
\usepackage{tikz}
\usepackage{transparent}

\makeatletter
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pgfutil@addpdfresource@extgs\endcsname\relax
\else
  \AtBeginDocument{%
    % \pgf@sys@addpdfresource@extgs@plain{%
    \pgfutil@addpdfresource@extgs{%
      \TRP@list
    }%
  }%  
  \let\TRP@addresource\relax
\fi
\makeatother

\begin{document}
Hello \texttransparent{.3}{World}
\begin{tikzpicture}
\filldraw[opacity=.5] (0,0) rectangle (1,1);
\end{tikzpicture}
\makeatletter 
\end{document}

\transparent也可以撤消对包的禁用ctable。警告仍然存在,但可以忽略。

\documentclass{standalone}
\usepackage{tikz}
\usepackage{transparent}
\let\OriginalTransparent=\transparent

\makeatletter
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pgfutil@addpdfresource@extgs\endcsname\relax
\else
  \AtBeginDocument{%
    % \pgf@sys@addpdfresource@extgs@plain{%
    \pgfutil@addpdfresource@extgs{%
      \TRP@list
    }%
  }%
  \let\TRP@addresource\relax
\fi
\makeatother

\usepackage{ctable}
\AtBeginDocument{%
  \let\transparent=\OriginalTransparent
}

\begin{document}
Hello \texttransparent{.3}{World}
\begin{tikzpicture}
\filldraw[opacity=.5] (0,0) rectangle (1,1);
\end{tikzpicture}
\makeatletter
\end{document}

相关内容