Several times I discovered the need to draw TikZ material behind and on top of the page text (How to draw text-anchored tikz line below text instead of above?, Test if a paragraph has a page break in it? and also Cool Text Highlighting in LaTeX). Most the time I need to draw from a start marker in the text towards a stop marker. As long as there are no page breaks between them I can draw in the text foreground when I draw from the end marker backwards (because the text is already typeset before) or in the background from the start marker forwards (because the text is typeset afterwards). However, as seen in How to draw text-anchored tikz line below text instead of above? this isn't perfect when drawing downwards to the right which goes over existing text to the left. Also in the case of one (or even multiple!) page break(s) between these markers the drawing must be split into multiple operations. Then it is difficult to ensure all material is placed in the correct layer.
My idea is now the following: I like to install a background and a foreground layer of the whole page and allow macros to place drawing commands on these layers. I think all commands can be accumulated and then processed when the page is shipped out. For this I found the atbegshi
package which provides access to the page as box. I now manipulate this box be placing it in a TikZ picture which is stored back in the same box register. See the example code below.
My question now is:
Is this an appropriate way to do it, i.e. is it safe to manipulate the page box like this or is there a better way to do this?
I now about \AtBeginShipoutUpperLeft
etc. but had problems using it with TikZ. Therefore I'm using the box in a node.
\documentclass{article}
\usepackage{atbegshi}
\usepackage{tikz}
\usetikzlibrary{backgrounds}
\usepackage{lipsum}
% Proof-of-concept
% Later these would be numbered to allow multiple per page
\def\mybgstart{%
\tikz[overlay,remember picture] { \draw [yellow] circle (1pt); \coordinate (bgstart); }%
\gdef\drawinbackground{\draw [yellow,line width=5mm] (bgstart) -- (bgend);}%
}
\def\mybgend{\tikz[overlay,remember picture] { \draw [blue] circle (1pt); \coordinate (bgend); }}
\def\myfgstart{%
\tikz[overlay,remember picture] { \draw [yellow] circle (1pt); \coordinate (fgstart); }%
\gdef\drawinforeground{\draw [purple,line width=5mm] (fgstart) -- (fgend);}%
}
\def\myfgend{\tikz[overlay,remember picture] { \draw [blue] circle (1pt); \coordinate (fgend); }}
\begin{document}
\lipsum[1-3] % for comparison
\clearpage
\makeatletter
\AtBeginShipout{%
\setbox\AtBeginShipoutBox\hbox{%
\color@setgroup
\begin{tikzpicture}[line width=1cm,remember picture]%
\path [use as bounding box] node [inner sep=0pt,outer sep=0pt] (A) {\box\AtBeginShipoutBox};
\begin{pgfonlayer}{background}
\draw [green,line width=1cm] (A.north east) -- (A.south west);
\drawinbackground
\global\let\drawinbackground\empty
\end{pgfonlayer}
\draw [red] (A.north west) -- (A.south east);
\drawinforeground
\global\let\drawinforeground\empty
\end{tikzpicture}%
\color@endgroup
}}
\makeatother
\lipsum[1]
\mybgstart\lipsum*[2]\unskip\mybgend
\lipsum[3]
\myfgstart\lipsum*[4]\unskip\myfgend
\lipsum[5-10]
\end{document}
PS: The above code works well with pdflatex
but I get an offset with latex
(DVI mode). With it the .aux
file holds different \pgfsyspdfmark
values. I there a way to fix that?