# Using tikzpagenodes with crop package?

Using the code from Background margin fill for (first line of) section titles?, I have this MWE:

\documentclass[10pt,twoside,openright]{book}

\usepackage[
paperwidth=15cm,
paperheight=20cm,
outer=2.5cm,
inner=2.5cm,
top=2.5cm,
bottom=2.5cm
]{geometry}
% \usepackage[a4,center]{crop}   % crop line
% \crop[cam,info]                % crop line

\usepackage{titlesec}
\usepackage{tikz}
\usetikzlibrary{external,calc}
\usepackage{tikzpagenodes}

\titleformat{\section}[hang]{\normalfont\Large\bfseries\color{black!90}}{\thesection}{1.5em}{\tikzexternaldisable\sectioncolouration{\Alph{section}}}[\tikzexternalenable]

\newcommand*\sectioncolouration[1]{%
\begin{tikzpicture}[baseline=(a.base), overlay, remember picture, inner xsep=0pt, outer sep=0pt]
\node  (a) {\phantom{\normalfont\Large\bfseries Xy}};
\path [fill=blue, fill opacity=.2, even odd rule] (current page.west |- a.north) -| (current page.east |- a.south) -| cycle (current page text area.west |- a.north) -| (current page text area.east |- a.south) -| cycle;
\ifodd\value{page}
\node at (a -| {$(current page text area.east)!1/2!(current page.east)$}) {#1};
\else
\node at (a -| {$(current page text area.west)!1/2!(current page.west)$}) {#1};
\fi
\end{tikzpicture}}

\begin{document}
\frontmatter
\mainmatter

\part{Introduction}
\chapter*{The first chapter - without thinking anything else}

\newpage

\section{The first section - and some more text inside; and some more text inside; and some more text inside}

Blah, blah, blah...

\begin{tikzpicture}[remember picture,overlay]
\draw[thick] (current page text area.north east) rectangle (current page text area.south west) ;
\end{tikzpicture}

\newpage
\section{This section starts on an even page}
Some text\dots

\end{document}


With the crop lines commented, as posted, everything is fine (after texing twice - click for full res):

But if I uncomment the crop lines, and recompile, then the output is corrupt:

It's as if current page text area (and even \ifodd\value{page}) cannot be determined if crop is active?!

Is there any way to get this code to work, even if crop is active?

• You are using a custom paper size? – cfr Mar 29 '15 at 23:24
• Thanks @cfr: Yes, I am - I shuffled the values shown in this MWE a bit, just to "genericize", but I still have a custom paper size in my actual doc... – sdaau Mar 29 '15 at 23:28
• You need to tell geometry. It thinks that your paper is 15x20cm when it is really 21x29.7cm. However, I'm losing the crop marks when I do this. – cfr Mar 29 '15 at 23:37
• You know that geometry has a showcrop of its own? That works fine... – cfr Mar 29 '15 at 23:40
• Thanks for that @cfr - good to know about the problems with geometry and losing cropmarks; had no idea about geometry's showcrop - but I'd prefer to get this working with the crop package (it was used in the original template I'm using). – sdaau Mar 29 '15 at 23:44

Here's a third answer. As the image shows, this does not correct the placement of the nodes added by tikzpagenodes. Rather, it compensates for the lies crop tells within the limited context of the section thumbs configuration.

\documentclass[10pt,twoside,openright]{book}

\usepackage[
paperwidth=15cm,
paperheight=20cm,
outer=2.5cm,
inner=2.5cm,
top=2.5cm,
bottom=2.5cm
]{geometry}
\usepackage[a4,center]{crop}   % crop line
\crop[cam,info]                % crop line

\usepackage{titlesec}
\usepackage{tikz}
\usetikzlibrary{external,calc}
\usepackage{tikzpagenodes}

\titleformat{\section}[hang]{\normalfont\Large\bfseries\color{black!90}}{\thesection}{1.5em}{\tikzexternaldisable\sectioncolouration{\Alph{section}}}[\tikzexternalenable]

\newcommand*\sectioncolouration[1]{%
\begin{tikzpicture}[baseline=(a.base), overlay, remember picture, inner xsep=0pt, outer sep=0pt]
\node  (a) {\phantom{\normalfont\Large\bfseries Xy}};
\ifx\stockwidth\undefined
\coordinate (b) at (0,0);
\else
\coordinate (b) at (.5\paperwidth-.5\stockwidth,.5\stockheight-.5\paperheight);
\fi
\begin{scope}
\path [fill=blue, fill opacity=.2, even odd rule] (current page.west |- a.north) -| (current page.east |- a.south) -| cycle ({$(current page text area.west) + (b)$} |- a.north) -| ({$(current page text area.east) + (b)$} |- a.south) -| cycle;
\ifodd\value{page}
\node at (a -| {$(current page text area.east)!1/2!(current page.east) + .5*(b)$}) {#1};
\else
\node at (a -| {$(current page text area.west)!1/2!(current page.west) + .5*(b)$}) {#1};
\fi
\end{scope}
\end{tikzpicture}}

\begin{document}
\frontmatter
\mainmatter

\part{Introduction}
\chapter*{The first chapter - without thinking anything else}

\newpage

\section{The first section - and some more text inside; and some more text inside; and some more text inside}

Blah, blah, blah...

\begin{tikzpicture}[remember picture,overlay]
\draw[thick] (current page text area.north east) rectangle (current page text area.south west) ;
\end{tikzpicture}

\newpage
\section{This section starts on an even page}
Some text\dots

\end{document}

• Thanks @cfr - I like this one the best; I just added an \ifx conditional, so the same code works if just the crop lines are commented. Btw, I also tried to work with \stockwidth, but as it can be seen from my answer below, couldn't really figure it out, so I took a different approach (via redef of top and left). Cheers! – sdaau Mar 30 '15 at 2:52
• @sdaau Note that this relies on the fact that you are passing center to crop, I think. Otherwise, you'd need to adjust the 0.5 appropriately in defining (b). – cfr Mar 30 '15 at 2:53

Ok, I think I have something, but am not exactly sure of it; the fix seems to be this:

\ifx\CROP@size\undefined
\typeout{CROP@size undefined}
\else
\typeout{CROP@size defined}
% must set via newlength so it survives descent into tikzpicture!
\setlength\gparindent{\parindent}
\setlength\gbaselineskip{\baselineskip}
\def\current@textarea@left{(1in+\hoffset+\currentsidemargin-\Gm@lmargin-\gparindent)}
\fi


... that is, if crop is loaded, redefine \current@textarea@left and \current@textarea@top from tikzpagenodes, so the left is adjusted by \Gm@lmargin-\gparindent and the right by 2*\Gm@tmargin-0.35\gbaselineskip - where \Gm@l/tmargin are margins via the geometry package.

The \gparindent and \gbaselineskip are "globalised" versions of parindent/baselineskip - as lengths - otherwise they won't propagate when the above definitions run inside tikzpicture (which resets parindent/baselineskip). The Gm@ margins make sense, but I have no idea why there is this displacement in there to begin with - I found the fix values via trial/error, so caveat emptor.

The code below has some extra debug stuff, and it outputs something like this:

Seems there is a tiny amount of bleed too - which is nice; also, all seems to work if you just comment the crop lines, as well.

The code:

\documentclass[10pt,twoside,openright]{book}

\usepackage[
paperwidth=15cm,
paperheight=20cm,
outer=3.5cm,
inner=2.5cm,
top=2.5cm,
bottom=3.5cm
]{geometry}
\usepackage[a4,center]{crop}
\crop[cam,info]

\usepackage{lipsum}

\usepackage{titlesec}
\usepackage{tikz}
\usetikzlibrary{external,calc}
\usepackage{tikzpagenodes}
\makeatletter
\newlength\gparindent
\newlength\gbaselineskip
\ifx\CROP@size\undefined
\typeout{CROP@size undefined}
\else
\typeout{CROP@size defined}
% from tikzpagenodes:
% NB: \parindent, \baselineskip seem to dissapear inside \sectioncolouration
%   \let\gparindent\parindent% NO
%   \xdef\gparindent{\parindent}% NO!
% must set via newlength so it survives descent into tikzpicture!
\setlength\gparindent{\parindent}
\setlength\gbaselineskip{\baselineskip}
\typeout{gparindent-Start \the\gparindent}%
\def\current@textarea@left{(1in+\hoffset+\currentsidemargin-\Gm@lmargin-\gparindent)}
% no need to repeat this:
%   \@newtikzpagenode{current page text area}{%
%     \def\southwest{\pgfpoint{\current@textarea@left}{\paperheight-\current@textarea@top-\textheight}}%
%     \def\northeast{\pgfpoint{\current@textarea@left+\textwidth}{\paperheight-\current@textarea@top}}%
%   }
\fi
\makeatother

\newcommand*\sectioncolouration[1]{%
\begin{tikzpicture}[baseline=(a.base), overlay, remember picture, inner xsep=0pt, outer sep=0pt]%
\typeout{gparindent-In-Sect-Col \the\gparindent}%
\node  (a) {\phantom{\normalfont\Large\bfseries Xy}};
\path [fill=blue, fill opacity=.2, even odd rule]
(current page.west |- a.north) -| (current page.east |- a.south) -| cycle
(current page text area.west |- a.north) -| (current page text area.east |- a.south) -| cycle;
%     (current page text area.south west) -| (current page text area.north east) -| cycle; % debug
\draw[red] (current page text area.north east) rectangle (current page text area.south west); % debug
\ifodd\value{page}
\node at (a -| {$(current page text area.east)!1/2!(current page.east)$}) {#1};
\else
\node at (a -| {$(current page text area.west)!1/2!(current page.west)$}) {#1};
\fi
\end{tikzpicture}}

\titleformat{\section}[hang]{%
\typeout{gparindent-Sect \the\gparindent}%
\setlength\gparindent{\parindent}%
\setlength\gbaselineskip{\baselineskip}%
\normalfont\Large\bfseries\color{black!90}%
}{\thesection}{1.5em}{\tikzexternaldisable\sectioncolouration{\Alph{section}}}[\tikzexternalenable]

\begin{document}
\frontmatter
\mainmatter

\part{Introduction}
\chapter*{The first chapter - without thinking anything else}

\newpage

\section{The first section - and some more text inside; and some more text inside; and some more text inside}

% debug
\begin{tikzpicture}[remember picture,overlay]
\draw[thick] (current page text area.north east) rectangle (current page text area.south west) ;
\draw[thick] (current page text area.east) rectangle ($(current page text area.west)+(0,1)$) ;
\end{tikzpicture}

\noindent
Blah, blah, blah... \lipsum[1-3]

%   \newpage
\section{This section starts on an odd page}
Some text\dots

\end{document}


crop appears to fundamentally disagree with tikzpagenodes. Or, rather, lying about your page layout, as crop requires, appears to fundamentally disagree with it. This is not terribly surprising. If the text area is not where you say, it isn't that surprising that things go haywire.

If geometry's crop marks are an option, these work fine:

\documentclass[10pt,twoside,openright]{book}
\usepackage[
paper=a4paper,
layoutsize={15cm,20cm},
layoutoffset={30mm,48.5mm},
outer=2.5cm,
inner=2.5cm,
top=2.5cm,
bottom=2.5cm,
showcrop,
]{geometry}
\usepackage{titlesec}
\usepackage{tikz}
\usetikzlibrary{external,calc}
\usepackage{tikzpagenodes}

\titleformat{\section}[hang]{\normalfont\Large\bfseries\color{black!90}}{\thesection}{1.5em}{\tikzexternaldisable\sectioncolouration{\Alph{section}}}[\tikzexternalenable]

\newcommand*\sectioncolouration[1]{%
\begin{tikzpicture}[baseline=(a.base), overlay, remember picture, inner xsep=0pt, outer sep=0pt]
\node  (a) {\phantom{\normalfont\Large\bfseries Xy}};
\path [fill=blue, fill opacity=.2, even odd rule] (current page.west |- a.north) -| (current page.east |- a.south) -| cycle (current page text area.west |- a.north) -| (current page text area.east |- a.south) -| cycle;
\ifodd\value{page}
\node at (a -| {$(current page text area.east)!1/2!(current page.east)$}) {#1};
\else
\node at (a -| {$(current page text area.west)!1/2!(current page.west)$}) {#1};
\fi
\end{tikzpicture}}

\begin{document}
\frontmatter
\mainmatter

\part{Introduction}
\chapter*{The first chapter - without thinking anything else}

\newpage

\section{The first section - and some more text inside; and some more text inside; and some more text inside}

Blah, blah, blah...

\begin{tikzpicture}[remember picture,overlay]
\draw[thick] (current page text area.north east) rectangle (current page text area.south west) ;
\end{tikzpicture}

\newpage
\section{This section starts on an even page}
Some text\dots

\end{document}

• Thanks for that @cfr; I'm trying to mess a bit with redefining tikzpagenodes if crop is loaded (I'm not progressing much though); if everything else fails, I'll eventually accept this answer... Cheers! – sdaau Mar 29 '15 at 23:46

I've been working on this problem from a more general angle.

From scanning the documentation of the crop package, it would seem like the most relevant values that we'd want to pull out are \stockwidth and \stockheight, which are used to store the ultimate paper size.

All we really need to do is redefine the main macros for tikzpagenodes to account for the difference between \stock* and \paper*. The code for this is

\def\current@textarea@left{%
(1in+\hoffset+\currentsidemargin+.5*(\paperwidth-\stockwidth))%
}
\def\current@textarea@top{%
}


Which just adds half of the difference between the \stock and \paper values to acccount for the offset. We only need half the value b/c the logical page is centered in the physical page, thus offset by half the difference.

To make a generic version of this, we'll do the following:

%fix the crop issue with tikzpagenodes
\@ifpackagewith{crop}{center}
{
\def\current@textarea@left{%
(1in+\hoffset+\currentsidemargin+.5*(\paperwidth-\stockwidth))}
\def\current@textarea@top{%
}
{
\def\current@textarea@top{%
}
}
{%
}


Now we can automatically adjust for the offset if the crop package is loaded. I also made a different adjustment for when the center option isn't used, where the \hoffset is fine and thus doesn't need adjustment, and the \voffset needs twice the adjustment (seeing as we're at the top left corner of the page).

I tested this both while typesetting RTL and LTR texts, using XeTeX.

It's actually interesting, because the center option actually sets \hoffset and \voffset to values which would be correct for our needs, but investigating that isn't necessary.