# (xe)tex: How do I apply \ifodd\pageno logic (\special) to image, based on page the box is set on, rather than when file is read

Working in (plain) XeTeX, I would like to apply a certain transformation (mirror on vertical axis) to an image if it appears on an odd-numbered page. I'd like a fairly general solution, as in some cases the image may end up in an insert, in others the image will just be added to the vertical list.

Naively I tried this (the image has been read into box0, full code below):

\def\beforeBox{\ifodd\pageno\kern\wd0\special{pdf: begintransform}\special{x:scale -1 1}\fi}%
\def\afterBox{\ifodd\pageno\special{pdf: endtransform}\fi}%


Which expanded immediately, and so mirrors the image if it is read while the page is odd (even if it is then displayed on the following one, once page-breaking has done its thing). I.e the logic works, but is applied too early.

\expandafter like this:

\setbox0\hbox{\expandafter\beforeBox\box0\expandafter\afterBox}%


seems not to help and, based on extra tracing calls included in the full code below, if I replace the expandafter with noexpand, then they are never expanded (not entirely surprisingly, but I thought I ought to check).

Is there some solution to this that doesn't involve writing page numbers to an external file? Some kind of \notimmediate that can delay logic until the page is built?

Minimal example showing problem:

\def\doimage#1#2{\setbox0\hbox{\XeTeXpicfile "#2" width #1}%
\setbox0\hbox{\beforeBox\box0\afterBox}%
\box0
}
\def\beforeBox{\immediate\write-1{beforeBox \the\pageno}\ifodd\pageno\kern\wd0\special{pdf: begintransform}\special{x:scale -1 1}\fi}%
\def\afterBox{\immediate\write-1{afterBox}\ifodd\pageno\special{pdf: endtransform}\fi}%
\def\junk{aut tempore sunt officia beatae libero ad non est autem unde reiciendis minima ut quasi sapiente atque non sed architecto et et culpa aliquam repellendus ipsam omnis qui sit est dolorem ab mollitia sed vero asperiores itaque quibusdam quos est repellat provident voluptatem fugit consequatur iste architecto temporibus\par}

\hsize=20em
\def\picsz{59pt}\def\filename{arrow.png}
\junk
\doimage{\picsz}{\filename}
\junk
\doimage{\picsz}{\filename}
\junk
\doimage{\picsz}{\filename}
\junk
\doimage{\picsz}{\filename}
\junk
\doimage{\picsz}{\filename}
\junk
\doimage{\picsz}{\filename}

\bye


Screenshot of result:

• The float is set in a box which waits for an opportunity to be unboxed. TeX needs to do it because it must know the size of the float. The page it will end up cannot be known at the moment the box is packaged and one cannot modify the contents of a box once it has been packaged. What's the problem with an auxiliary file? – egreg Jul 24 '20 at 11:35
• The problelm with an auxilliary file is that it needs a second run, and that's always struck me as a messy solution if not needed to actually redefine the text-contents. It also adds the requirement that I keep a counter for images, adds extra overhead of a \csname per image, maybe some logic to say 'a rerun may be required' and so on. It all seemed like it ought to be overkill for "this little problem" and I was hoping it wasn't needed. – somloigaluska Jul 24 '20 at 12:08
• Once the page is done, you cannot change anything. You could use the everypage package to overlay an image, but IIRC it will go under anything opaque. – John Kormylo Jul 24 '20 at 12:30
• Actually, your problem is slightly different from floats, but the problem is the same: TeX always typesets more than will fit in a page and only later it will decide to output a page breaking at the “best” place. This means that your image might be encountered before the page number is incremented (which is only done when pages are being output). – egreg Jul 24 '20 at 12:56
• Noticing this question only now and I don't know if you still care, but I imagine this may be possible with LuaTeX and use of the appropriate hooks (probably pre_output_filter), possibly along with some use of whatsits on the TeX end, for the Lua code to be able to recognize the images that need the transformation. With LuaHBTeX available now (TeX Live 2020 onwards IIRC), it seems a practical alternative to plain XeTeX. – ShreevatsaR Dec 29 '20 at 0:38