# How to fix this \special{pdf: content …} so it doesn't corrupt the resulting PDF?

I use a \special command to drive some diagonal lines as a part of a macro for drawing puzzles. While these work fine when compiling with XeTeX, they seem to corrupt the resulting PDF document when using pdftex instead. Here is a minimal reproducable example:

\special{pdf: content q 0 G 0.4 w
0   8 m  2  10 l
0   6 m  4  10 l
0   4 m  6  10 l
0   2 m  8  10 l
0   0 m 10  10 l
0  -2 m 12  10 l
0  -4 m 14  10 l
0  -6 m 16  10 l
0  -8 m 18  10 l
0 -10 m 20  10 l
2 -10 m 20   8 l
4 -10 m 20   6 l
6 -10 m 20   4 l
8 -10 m 20   2 l
10 -10 m 20   0 l
12 -10 m 20  -2 l
14 -10 m 20  -4 l
16 -10 m 20  -6 l
18 -10 m 20  -8 l
S Q}
\bye


When I open the resulting document in Adobe Acrobat or with Ghostscript, it'll complain about a defective page. E.g. for pdf2ps we have:

\$ pdf2ps test.pdf
**** Error: File did not complete the page properly and may be damaged.
Output may be incorrect.


What could the problem be? How can I change the \special command to fix this issue?

• Just replace \special{pdf: content with \pdfliteral{ – AlexG Dec 1 '20 at 15:26
• @AlexG Doesn't seem to work with XeTeX though. Is there a solution that works for both (aside from writing a compatibility shim)? – FUZxxl Dec 1 '20 at 15:30
• @AlexG Thanks. I found that \special{pdf: ...} (without the content clause) also works. Would you mind writing up an answer? – FUZxxl Dec 1 '20 at 15:40
• \special{pdf: ...} doesn't work for me with xetex. The page is empty. – AlexG Dec 1 '20 at 15:50

I would go with a conditional to abstract the backend differences

\ifdefined\XeTeXversion
\protected\def\myspecial#1{\special{pdf:content q #1 Q}}
\else
\protected\def\myspecial#1{\pdfliteral{q #1 Q}}
\fi
\myspecial{%
0 G 0.4 w
0   8 m  2  10 l
0   6 m  4  10 l
0   4 m  6  10 l
0   2 m  8  10 l
0   0 m 10  10 l
0  -2 m 12  10 l
0  -4 m 14  10 l
0  -6 m 16  10 l
0  -8 m 18  10 l
0 -10 m 20  10 l
2 -10 m 20   8 l
4 -10 m 20   6 l
6 -10 m 20   4 l
8 -10 m 20   2 l
10 -10 m 20   0 l
12 -10 m 20  -2 l
14 -10 m 20  -4 l
16 -10 m 20  -6 l
18 -10 m 20  -8 l
S}
\bye



(This could be extended for DVI mode, LuaTeX, etc.)

If you want to have everything inside a macro, one could go with

\protected\def\myspecial#1{%
\special{%
\ifdefined\XeTeXversion
pdf:content q #1 Q
\else
pdf:q #1 Q
\fi
}%
}
\myspecial{%
0 G 0.4 w
0   8 m  2  10 l
0   6 m  4  10 l
0   4 m  6  10 l
0   2 m  8  10 l
0   0 m 10  10 l
0  -2 m 12  10 l
0  -4 m 14  10 l
0  -6 m 16  10 l
0  -8 m 18  10 l
0 -10 m 20  10 l
2 -10 m 20   8 l
4 -10 m 20   6 l
6 -10 m 20   4 l
8 -10 m 20   2 l
10 -10 m 20   0 l
12 -10 m 20  -2 l
14 -10 m 20  -4 l
16 -10 m 20  -6 l
18 -10 m 20  -8 l
S}
\bye

• It's actually something OP wanted to avoid (engine detecting shim). – AlexG Dec 1 '20 at 16:48
• @AlexG Feel free to edit: I didn't double-check the q/Q situation. My reading of the question is it doesn't rule out the approach I've suggested. Although as \special does expansion, one could put it inside the literal. – Joseph Wright Dec 1 '20 at 17:13

I ended up using

\special{pdf:content ...}


(note the lack of space between pdf: and content). This seems to work fine with both pdfTeX and XeTeX.

• It doesn't (pdftex). Check with pdf2ps, Ghostscript complains. The string content is put verbatim into the page stream which is an error because there is no PDF operator named like this. – AlexG Dec 10 '20 at 14:01
• @AlexG Indeed, how strange. It did work when I tried it a few days ago and I had accepted an answer already (which has since been deleted). – FUZxxl Dec 10 '20 at 14:15
• Yes, the deleted answer was mine. I flagged it for deletion after I discovered that there is no common special for both xetex and pdftex. You may need to use @Joseph's solution which queries the TeX engine in use. – AlexG Dec 10 '20 at 14:19
• @AlexG How unfortunate. – FUZxxl Dec 10 '20 at 15:13