4

I use this code (fixed by marmot :) ...), which worked perfectly until a point where my document got too many pages.
At a given point I get a "Dimension too large" error. It uses code that tests if a given tikzmark is on a page, so my hunch is that the problem lies there somewhere, that too many pages cause trouble... Alas, I have no clue whatsoever how to troubleshoot.

Given the nature of the problem, the following is an "as-minimal-as-it-gets-not-working-example" :) (If you delete two rows of the \repeatenoughtimes macro you will get it to work ... just to show that the problem has definitely to do with repeating it too often.)

% !TEX TS-program = xelatexmk
\documentclass{article}
%\usepackage[a6paper]{geometry}
\usepackage[paperwidth=4in,paperheight=3in]{geometry}
%\url{https://tex.stackexchange.com/q/483547/86}
\usepackage{tikz}
\usepackage{tikzpagenodes}
\usetikzlibrary{tikzmark}
\newcounter{tikzmarklines}\setcounter{tikzmarklines}{0} % 

%% Code added recently to the package which provides the \iftikzmarkoncurrentpage code: 
\makeatletter

\newif\iftikzmark@
\renewcommand\iftikzmark[3]{%
    \@ifundefined{save@pt@\tikzmark@pp@name{#1}}{%
      #3%
    }{%
      #2%
    }%
}%

\newcommand\iftikzmarkexists[1]{%
  \@ifundefined{save@pt@\tikzmark@pp@name{#1}}{%
    \tikzmark@false%
  }{%
    \tikzmark@true%
  }%
  \iftikzmark@
}%

\newcommand\iftikzmarkonpage[2]{%
  \@ifundefined{save@pt@\tikzmark@pp@name{#1}}{%
    \tikzmark@false
  }{%
    \@ifundefined{save@pg@\csname save@pt@\tikzmark@pp@name{#1}\endcsname}{%
      \tikzmark@false
    }{%
      \ifnum\csname save@pg@\csname save@pt@\tikzmark@pp@name{#1}\endcsname\endcsname=#2\relax%
      \tikzmark@true
      \else
      \tikzmark@false
      \fi
    }%
  }%
  \iftikzmark@
}

\newcommand\iftikzmarkoncurrentpage[1]{%
  \@ifundefined{save@pt@\tikzmark@pp@name{#1}}{%
    \tikzmark@false
  }{%
    \@ifundefined{save@pg@\csname save@pt@\tikzmark@pp@name{#1}\endcsname}{%
      \tikzmark@false
    }{%
      \ifnum\csname save@pg@\csname save@pt@\tikzmark@pp@name{#1}\endcsname\endcsname=\the\value{page}\relax%
      \tikzmark@true
      \else
      \tikzmark@false
      \fi
    }%
  }%
  \iftikzmark@
}
\makeatother

\tikzset{
  next page=below,
  brace/.style n args={2}{insert path={%
  ([xshift=0.15em,yshift=0.1pt+.5ex]#1) -- 
  ([xshift=-0.3pt,yshift=0.1pt+.5ex]#1) -- 
  ([xshift=-0.3pt,yshift=-0.1pt+.5ex]#2) -- 
  ([xshift=0.15em,yshift=-0.1pt+.5ex]#2) -- 
  ([xshift=0.15em,yshift=0.1pt+.5ex]#2) --
  ([xshift=0.3pt,yshift=0.1pt+.5ex]#2) --
  ([xshift=0.3pt,yshift=-0.1pt+.5ex]#1) --
  ([xshift=0.15em,yshift=-0.1pt+.5ex]#1) --
  cycle}}}

\newif\iffirstmark

\newcommand{\linestart}{%
  \stepcounter{tikzmarklines}%
  \tikzmark{a\thetikzmarklines}%
  \global\firstmarktrue
  \iftikzmarkoncurrentpage{b\thetikzmarklines}%
  \else
  \begin{tikzpicture}[remember picture,overlay,next page=below]%
  \clip (current page text area.south west) rectangle (current page text area.north east);
  \fill[overlay,brace={pic cs:a\thetikzmarklines}{pic cs:b\thetikzmarklines}];
  \end{tikzpicture}%
  \fi
}

\newcommand{\linefinish}{%
  \iffirstmark
  \tikzmark{b\thetikzmarklines}%
  \global\firstmarkfalse
  \fi
  \begin{tikzpicture}[remember picture,overlay]%
  \clip (current page text area.south west) rectangle (current page text area.north east);
  \fill[overlay,brace={pic cs:a\thetikzmarklines}{0,0}];
  \end{tikzpicture}%
  }

\usepackage{lipsum}

\newcommand{\repeatenoughtimes}{
Text \linestart text text\par
Text text \linefinish text\par
Text \linestart text text\par
Text text \linefinish text\par
\lipsum[1-5]
}

\begin{document} 

\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes
\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes
\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes
\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes
\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes\repeatenoughtimes

\end{document}
jan
  • 2,236
  • I am not convinced that the number of repetitions is the problem. If I use \lipsum[1-2] instead of \lipsum[1-5], the error goes away. –  Apr 15 '19 at 16:03
  • @marmot But then if you add a few more \repeatenoughtimes, you get the error back :( ... hence my hunch it's the page count ??? ... but honestly I have no idea... – jan Apr 15 '19 at 16:35

2 Answers2

4

(To long for a comment). It is a bug in tikzmark and related to the next page option. It multiplies \pgf@y by the page number, and with a large enough page number it explodes.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\tikzset{
  next page=below,
 }
\begin{document}
\setcounter{page}{30}
\tikzmark{blub}\tikz[remember picture]\draw(pic cs:blub);
\end{document}
Ulrike Fischer
  • 327,261
2

Here's my proposed fix. To try it out, put it between \makeatletter ... \makeatother in your preamble after loading the tikzmark library.

It's entirely possible that I don't understand how \numexpr or dimensions work, but the idea is sound.

\tikzdeclarecoordinatesystem{pic}{%
  \pgfutil@in@,{#1}%
  \ifpgfutil@in@%
    \tmk@labeldef#1\@nil
  \else
    \tmk@labeldef#1,(0pt,0pt)\@nil
  \fi
  \@ifundefined{save@pt@\tmk@label}{%
    \tikz@scan@one@point\pgfutil@firstofone\tmk@def
  }{%
    \pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}%
    \save@orig@pic%
    \pgfsys@getposition{\pgfpictureid}\save@this@pic%
    \pgf@process{\pgfpointorigin\save@this@pic}%
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    \pgf@process{\pgfpointorigin\save@orig@pic}%
    \advance\pgf@x by -\pgf@xa
    \advance\pgf@y by -\pgf@ya
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    \pgf@process%
    {\pgfpointorigin\csname save@pt@\tmk@label @offset\endcsname}%
    \advance\pgf@xa by \pgf@x
    \advance\pgf@ya by \pgf@y
      \@ifundefined{save@pg@\csname save@pt@\tmk@label\endcsname}{}{%
        \@ifundefined{save@pg@\pgfpictureid}{}{%
          \pgfkeysvalueof{/tikz/next page vector}%
        \edef\tmk@pg{\the\numexpr \csname save@pg@\csname save@pt@\tmk@label\endcsname\endcsname - \csname save@pg@\pgfpictureid\endcsname\relax}%
        \advance \pgf@xa by %
        \tmk@pg\pgf@x\relax
        \advance \pgf@ya by %
        \tmk@pg\pgf@y\relax
        }%
      }%
      \pgf@x=\pgf@xa
      \pgf@y=\pgf@ya
    \pgftransforminvert
    \pgf@pos@transform{\pgf@x}{\pgf@y}%
    }%
  }
Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • It works up until page 3662, so definitely sufficient for my current purposes ;) but (using @UlrikeFischer 's example) with \setcounter{page}{3663} and higher it still fails ... – jan Apr 16 '19 at 07:10
  • To make it work with more pages I'd need to reimplement the next page concept. I could add a warning that it only works with documents at most 3662 pages long ...

    I've added this to the tikzmark code on github.

    – Andrew Stacey Apr 20 '19 at 11:01
  • I think it's safe to assume that people with an over-3662-page document might need the iftikzmarkonpage up to page 3661 but I doubt they will need it on the next page ... just my feeling ;P – jan Apr 20 '19 at 17:08