Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fading produces corrupt PDF #824

Closed
dcpurton opened this issue Jan 13, 2020 · 28 comments
Closed

Fading produces corrupt PDF #824

dcpurton opened this issue Jan 13, 2020 · 28 comments

Comments

@dcpurton
Copy link
Contributor

My printer (person, not machine) is complaining that a file I've sent crashes his RIP. I'm not 100% sure, but I suspect the problem is due to a fading I have used, as it's the only unusual thing in the file. I can also produce a PDF containing only a simple fading that crashes Adobe Reader 9 under Linux when exporting to PostScript.

This MWE crashes Adobe Read 9 when exporting to PostScript when built with both pdflatex and lualatex. It seems OK with xelatex.

\documentclass{article}

\usepackage{tikz}

\pgfdeclareverticalshading{myshading}{100bp}
  {color(0bp)=(transparent!100); color(25bp)=(transparent!100);
   color(27.5bp)=(transparent!40); color(75bp)=(transparent!40);
   color(100bp)=(transparent!40)}
\pgfdeclarefading{myfading}{\pgfuseshading{myshading}}

\begin{document}

\begin{tikzpicture}
  \path[fill=black, path fading=myfading] (0,0) rectangle (5,5);
\end{tikzpicture}

\end{document}
@hmenke hmenke added the fadings label Jan 13, 2020
@hmenke
Copy link
Member

hmenke commented Jan 13, 2020

Is it reproducible with older versions, i.e. is it a regression?

@dcpurton
Copy link
Contributor Author

I don't know. I am running 3.1.4b. I have to do some more testing on other types of transparency. I guess overleaf still has a pretty old version of tikz. I'll test on that. I can't easily install older versions on my machine.

@dcpurton
Copy link
Contributor Author

OK, this is not a regression. The following even simpler file also causes acroread v9 to segfault when outputting PostScript. This happens with v3.0.1a from Overleaf as well.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{fadings}

\begin{document}

\begin{tikzpicture}
  \path[fill=black, path fading=south] (0,0) rectangle (5,5);
\end{tikzpicture}

\end{document}

@dcpurton
Copy link
Contributor Author

It's definitely worth checking this more carefully than relying on the acroread behaviour though. It's not exactly a bug free piece of software… I just don't have anything else.

@pablgonz
Copy link

@dcpurton I have checked the problem using Acrobat DC pro is present only with (pdf|lua)latex, with xelatex it works perfect. If you reconvert to .psusing pdf2ps and then switch back to .pdf using ps2pdf the problem disappears. Sending to print from other pdf viewers works ok using (pdf|lua)latex.

@dcpurton
Copy link
Contributor Author

@pablgonz GhostScript doesn't handle transparency very well. It's slow and tends and rasterize very large sections of the page.

My printer accepted the document once I pre-flattened the fading, so this was definitely the problem.

The /Shading PDF objects are identical between lualatex and xelatex. So the difference is in how they are used.

@pablgonz
Copy link

@dcpurton The truth is I've never had a problem with GS :)

The /Shading PDF objects are identical between lualatex and xelatex. So the difference is in how they are used.

I don't know if that's really true, the internal structure of the .pdf file created by luatex and xelatex differs a bit, at least that I can see by analyzing it with Adobe DC pro (win10) and with pdf-parser (Ubuntu 18).

@hmenke hmenke added this to the 3.1.6 milestone Jan 26, 2020
@hmenke
Copy link
Member

hmenke commented Jan 26, 2020

Adobe Reader 9 segfaulting is not good measure, because it's unsupported, old, 32-bit only, and has remote code execution vulnerabilities, so should not be used under any circumstances anyway.

For easier PDF inspection you can add this at the start of your document:

\ifdefined\directlua
    \edef\pdfcompresslevel{\pdfvariable compresslevel}
    \edef\pdfobjcompresslevel{\pdfvariable objcompresslevel}
\fi
\ifdefined\pdfcompresslevel
    \pdfcompresslevel=0
    \pdfobjcompresslevel=0
\else
    \special{dvipdfmx:config z 0}
\fi

@hmenke
Copy link
Member

hmenke commented Feb 14, 2020

@dcpurton Have a look at #833. Seems to be the same problem, but there only under macOS.

@dcpurton
Copy link
Contributor Author

@hmenke , Thanks for the tip on making dvipdfmx produce an uncompressed PDF. I didn't know this, I've always just use pdftk for xelatex! (But I was checking things with an uncompressed PDF with lualatex as you have above.)

@pablgonz I said that the /Shading object was the same, but looking more carefully I did miss one difference.

There are 8 /Shading objects produced by a similar MWE to the second one above (I think this one uses \usepackage[gray]{xcolor}).

With lualatex, the first is:

<< /Shading << /Sh << /ShadingType 2 /ColorSpace /DeviceGray /Domain [0.0 100.00128] /Coords [0.0 0 100.00128 0] /Function << /FunctionType 3 /Domain [0.0 100.00128] /Functions [ << /FunctionType 2 /Domain [0.0 100.00128] /C0 [1] /C1 [1] /N 1 >>  << /FunctionType 2 /Domain [0.0 100.00128] /C0 [1] /C1 [0] /N 1 >>  << /FunctionType 2 /Domain [0.0 100.00128] /C0 [0] /C1 [0] /N 1 >>  ] /Bounds [ 25.00032 75.00096] /Encode [0 1  0 1 0 1] >> /Extend [false false] >> >> /ProcSet [ /PDF ] >>

And with xelatex:

<</Shading<</Sh<</ShadingType 2/ColorSpace/DeviceGray/Domain[0 100.00128]/Coords[0
0 100.00128 0]/Function<</FunctionType 3/Domain[0 100.00128]/Functions[<</FunctionType
2/Domain[0 100.00128]/C0[1]/C1[1]/N 1>><</FunctionType 2/Domain[0 100.00128]/C0[1]/C1[0]/N
1>><</FunctionType 2/Domain[0 100.00128]/C0[0]/C1[0]/N 1>>]/Bounds[25.00032 75.00096]/Encode[0
1 0 1 0 1]>>/Extend[false false]>>>>/ProcSet[/PDF/Text/ImageC/ImageB/ImageI]>>

The /ProcSet at the end is different. I don't know the implications of this though. Best I can see apart from this, all 8 objects are the same. It's difficult to diff them because of spacing and line break differences though and I haven't checked it thoroughly.

As for Adobe Reader, I know it's a bad option, but the reality is that there is no other open source PDF reader that spits out PostScript as good as Adobe Reader. So If I want to print to my PostScript printer and not have CUPS screw with my colours by converting everything through an RGB PDF, there is no other choice.

#833 is possibly the same problem, but externalising the figures does change behaviour. And of course the engines causing problems (as reported) are different to this issue.

The MWE in #833 crashes acroread when exporting to PostScript for me when building the example with lualatex. It's OK for both pdflatex and xelatex though. Interesting that it works with pdflatex though, since pdflatex definitely causes a segfault with the MWEs in this issue. But you can get lucky with Segfaults of course, so the problem could still be there.

If I remove tikzexternalize[prefix=figures/] then behaviour is the same as this issue. (only xelatex works.)

@letzfets
Copy link

@dcpurton Have a look at #833. Seems to be the same problem, but there only under macOS.

Not sure if they are actually the same. @dcpurton 's MWE works fine on my machine and with both of my viewers, but #833 does show at all.
But I nailed it down to: it's not pgf and it's not xelatex or pdflatex, because I viewed the file, that was generated on my Mac with my Android phone. Everything was fine there. Note same file, no processing. On Android I had an Acrobat Reader.
Is this coming back to the old dispute between Steve Jobs and the Adobe folks?

@dcpurton
Copy link
Contributor Author

@letzfets , it's tempting to blame viewers. But when it gets to the point of a commercial print job being rejected by a printer because it crashes their RIP (which was my experience), it doesn't matter.

In all likelyhood the printer is using an Adobe RIP, and Adobe, not Apple, gets to decide what is valid PDF. For printing I usually prefer to avoid transparency altogether as it always leaves a bit to chance. But this is 2020, and I shouldn't have to pre-flatten everything. Besides, unlike applications like InDesign and Illustrator, LaTeX has no way to flatten things at compile time.

@hmenke
Copy link
Member

hmenke commented Feb 17, 2020

@dcpurton There was a typo in \pgfsys@usefading in both the LuaTeX and the pdfTeX driver. Could you try this patch? (it's not on master yet)

diff --git a/tex/generic/pgf/systemlayer/pgfsys-luatex.def b/tex/generic/pgf/systemlayer/pgfsys-luatex.def
index 8a81d981..9a854899 100644
--- a/tex/generic/pgf/systemlayer/pgfsys-luatex.def
+++ b/tex/generic/pgf/systemlayer/pgfsys-luatex.def
@@ -289,7 +289,7 @@
     \pgferror{Undefined fading '#1'}%
   \else%
     {%
-      \expandafter\ifx\csname pgfsmaks@#1\endcsname\relax%
+      \expandafter\ifx\csname pgfsmask@#1\endcsname\relax%
         \pgf@sys@pdf@install@mask{#1}%
       \fi%
       \pgftransformreset%
diff --git a/tex/generic/pgf/systemlayer/pgfsys-pdftex.def b/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
index 1f141780..510a4cca 100644
--- a/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
+++ b/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
@@ -286,7 +286,7 @@
     \pgferror{Undefined fading '#1'}%
   \else%
     {%
-      \expandafter\ifx\csname pgfsmaks@#1\endcsname\relax%
+      \expandafter\ifx\csname pgfsmask@#1\endcsname\relax%
         \pgf@sys@pdf@install@mask{#1}%
       \fi%
       \pgftransformreset%

@dcpurton
Copy link
Contributor Author

@hmenke Good catch!

But I still see the Segfault when outputting to PostScript from acroread though. :(.

(Assuming I tested right, but I'm pretty sure I did. And assuming that the acroread Segfault is a reliable marker for the bug, which might not be the case.)

@letzfets
Copy link

@letzfets , it's tempting to blame viewers. But when it gets to the point of a commercial print job being rejected by a printer because it crashes their RIP (which was my experience), it doesn't matter.

In all likelyhood the printer is using an Adobe RIP, and Adobe, not Apple, gets to decide what is valid PDF. For printing I usually prefer to avoid transparency altogether as it always leaves a bit to chance. But this is 2020, and I shouldn't have to pre-flatten everything. Besides, unlike applications like InDesign and Illustrator, LaTeX has no way to flatten things at compile time.

Valid point @dcpurton. Well, as far as I can google, there is a standard for pdf: ISO 32000-2. I didn't buy it but somehow I should have access to it through my job. So theoretically I could find out, what it says about fading, but then I couldn't post it here, because the iso.org wants money for this information. :(

@dcpurton
Copy link
Contributor Author

@letzfets, the PDF spec is available online (this essentially became the ISO standard): https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdf_reference_archive/pdf_reference_1-7.pdf

@ilayn
Copy link
Member

ilayn commented Mar 4, 2020

Make your shading 50bp instead of 100bp

@hmenke
Copy link
Member

hmenke commented May 30, 2020

@dcpurton Have you had a chance to try out Ilhan's suggestion?

@dcpurton
Copy link
Contributor Author

@hmenke, using a 50bp wide shading makes no difference. Still crashes acroread. I can confirm that these files also crash Acrobat Pro 8 under (running under WINE) when exporting to PostScript (even though Acrabat's low level PDF analysis reports no problems. This is true with and without your typo fix.

@u-fischer
Copy link
Contributor

The /ProcSet at the end is different. I don't know the implications of this though

if the setting is the cause of your crash then I see no easy way to change this. Which entries are added here is choosen by the engine and there is no way to replace the values.

You could try to add in (a local copy of) pdfsys-pdftex.def in the various shading definitions an extended proc set:

  \immediate\pdfxform resources {%
      /ProcSet [/PDF/Text/ImageC/ImageB/ImageI] /Shading

and look if this help. But it means that the resources will contain both the extended set and the one inserted by pdftex , so basically this makes the pdf invalid, so it is only useful for testing.

@dcpurton
Copy link
Contributor Author

@u-fischer I (carefully) hand edited the PDF and changed the /ProcSet, but it still SegFaults :(

@dcpurton
Copy link
Contributor Author

I checked the shading dictionaries and its definitely the same between xelatex and pdflatex except for the /ProcSet. The file structure is quite different though, so finding what actually is different is not very easy :(.

@u-fischer
Copy link
Contributor

One difference I saw is in the stream of the xobject:

xlatex

stream
 0 G 0 g /Sh sh
endstream

pdflatex

stream
/Sh sh
endstream

You could check if it matters by changing in pgfsys-pdftex.def in \def\pgfsys@horishading the third line to

\setbox\pgfutil@tempboxa=\hbox to\pgf@max{\vbox to\pgfmathresult pt{\vfil\pgfsys@invoke{0 G 0 g /Sh sh}}\hfil}%

@dcpurton
Copy link
Contributor Author

@u-fischer , adding the stroke and fill colours doesn't help either :(.

@hmenke
Copy link
Member

hmenke commented Jul 3, 2020

This issue is still lacking path to reproduce reliably on other platforms than used by the original author. Feel free to reopen once you have a proper testcase. Until then I'm closing as works-for-me.

@hmenke hmenke closed this as completed Jul 3, 2020
@dcpurton
Copy link
Contributor Author

dcpurton commented Jul 3, 2020

@hmenke I think @u-fischer did reproduce this under Windows. And I did get it to happen with Acrobat Pro 8 under Wine too. I don't have access to anything newer.

@hmenke
Copy link
Member

hmenke commented Jul 3, 2020

I don't think Ulrike was able to reproduce. I'd like to reiterate that reproducing with Adobe products does not help. First, the Linux version is seriously outdated, has unfixed security vulnerabilities, and is 32-bit only. Second, I don't have a license for Adobe Acrobat Pro and I'm not going to buy one just to reproduce this bug. Third, Adobe products being closed source are problematic for the fact that even if I manage to make it crash, I can't just recompile and attach a debugger to see where it crashed.
Although, now that you mention it, since you are a paying customer, you could send the PDF to Adobe and tell them that it crashes their program and ask them to tell you what's wrong with it.

@u-fischer
Copy link
Contributor

I was able to reproduce it: https://chat.stackexchange.com/transcript/message/54528648#54528648. And I just tried again: An export to postscript fails, Acrobat shows a dialog that some internal error happened. It works with xelatex.

It fails already if one simply loads the fading but doesn't use it:

\RequirePackage{l3pdf}
\ExplSyntaxOn
\pdf_uncompress:
\ExplSyntaxOff

\documentclass{article}

\usepackage{tikz}

\pgfdeclareverticalshading{myshading}{100bp}
  {color(0bp)=(transparent!100); color(25bp)=(transparent!100);
   color(27.5bp)=(transparent!40); color(75bp)=(transparent!40);
   color(100bp)=(transparent!40)}
\pgfdeclarefading{myfading}{\pgfuseshading{myshading}}

\begin{document}
\setbox0\hbox{%
\begin{tikzpicture}
  \path[fill=black, path fading=myfading] (0,0) rectangle (5,5);
\end{tikzpicture}}
\begin{tikzpicture}
  \path[fill=black] (0,0) rectangle (5,5);
\end{tikzpicture}

\end{document}

The only obvious difference that I see is that with pdflatex/lualatex there is an additional layer of indirection: An xobject with /Fm2 refers to an object with /Fm1 which refers to an object with /Sh which refers to the shading dict. xelatex has one layer less. But I'm not sure yet, how to test if this is the problem (and I don't know who is creating the additional layer here and if one can suppress it). Perhaps I have some time during the weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants