3

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?

4
  • 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
2

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
2
  • 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
0

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.

4
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.