10

I would like to measure the total height of a \vbox even for boxes which are larger than \maxdimen. It would be enough, if the code would compute the total height correctly only for small boxes. For very large boxes, a 'is very large' statement would be enough.

I followed the suggestions given in the answer to Long frames in mdframed and made the following test code which is able to measure a \vbox correctly in this sense for a total height up to 4 times of \maxdimen.

\documentclass{article}

\usepackage{blindtext}

\begin{document}

\newbox\largebox
\newdimen\measuredHeight

\newcommand*{\measureBox}[1]{%
  \chardef\previousinteractionmode=\interactionmode%
  \batchmode%
  \measuredHeight=\dimexpr\ht#1+\dp#1\relax%
  \ifdim\measuredHeight<0pt\relax%
    \measuredHeight=\maxdimen%
  \else\ifdim\measuredHeight=0pt\relax%
    \ifdim\ht#1>0pt\relax%
      \measuredHeight=\maxdimen%
  \fi\fi\fi%
  \interactionmode\previousinteractionmode%
}

\newcommand*{\blindtexttest}[1]{%
  Blindtext[#1]:
  \setbox\largebox\vbox{\blindtext[#1]}%
  \measureBox{\largebox}%
  total height
  \ifdim\measuredHeight<\maxdimen\relax
    \the\measuredHeight%
  \else%
    \the\maxdimen\ or larger%
  \fi%
  \par%
}

\newcount\mytest
\mytest=0
\loop
  \advance\mytest by 1
  \blindtexttest{\the\mytest}
\ifnum\mytest<550\repeat

\end{document}

enter image description here

...

enter image description here

On the negative side, this code produces a lot of ! Arithmetic overflow and ! Dimension too large messages in the log file. These messages are correct but annoying.

So, my first question is: How could I suppress these messages? How can I make the \measureBox command as silent as possible?

My general question is: Can you give me a better code for \measureBox? This macro takes a box register as parameter and saves the computed or guessed total height into \measuredHeight.

A better code would give less annoying messages and, if possible, would measure boxes which are larger than 4 times \maxdimen.

  • why put so much in a box? can't you just accumulate the content paragraph by paragraph and add a paragraph at a time, and do something when you are about to exceed maxdimen? – David Carlisle Jul 3 '14 at 15:43
  • @DavidCarlisle This is an MWE for a possible enhancement of tcolorbox. Currently, the largest breakable box cannot be longer than \maxdimen. With the somehow improved code above, this upper bound could be increased (maybe, by factor 4). – Thomas F. Sturm Jul 3 '14 at 15:49
  • You can check whether an overlong vbox is empty without error; so you can repeatedly \vsplit it until it becomes empty. – egreg Jul 3 '14 at 15:49
  • @ThomasF.Sturm so I guessed, but as I say why put so much in a box, you could collect the tcolorbox content in smaller chunks. Presumably if it is large you are going to vsplit or unbox it anyway. – David Carlisle Jul 3 '14 at 15:53
  • @egreg Currently, I need a preview of the total height in my algorithm, but maybe that could be changed. Until today, I was not aware that a \vbox could become very large without error if I do not ask about the height. – Thomas F. Sturm Jul 3 '14 at 16:03
8

The allowed range for dimensions in TeX is (-230+1) sp to (230-1) sp, the latter is \maxdimen (16383.99998 pt). However, TeX stores dimension registers as 32 bit numbers and it does not check for the allowed dimen range, if the dimen is used as number.

If the height of the large box is not negative, then we can measure the height of a box from 0pt up to 65535.99998 pt, that is 4 * \maxdimen + 3 sp = (232 - 1) sp. If the height of the box is larger, then we get only the lowest 32 bits of the height, because TeX stores the height as 32 bit number. Therefore it is not known, if the value is correct or if an integer multiple of 232 sp has to be added, and the phrase "or larger" can be added for all values.

The following example defines \DefPositiveDimenValue. It takes the dimen value as second argument (height/depth/width of a box, dimen register, ...) and stores the value with unit pt in the macro, given as first argument. Larger values than \maxdimen are calculated via package fp.

\documentclass{article}

\usepackage{blindtext}
\newbox\largebox

\usepackage{fp,fp-snap}
\makeatletter

\newcommand*{\DefPositiveDimenValue}[2]{%
  \ifnum#2<0 %
    \begingroup
      \FPmessagesfalse
      \count@=#2\relax
      \advance\count@ by 2147483647\relax
      \advance\count@ by 1\relax
      \ifnum\count@<\maxdimen
        \FPadd#1{\strip@pt\dimexpr\count@ sp}{32768}%
      \else
        \advance\count@ by -1073741824\relax
        \FPadd#1{\strip@pt\dimexpr\count@ sp}{49152}%
      \fi
      \FPclip#1#1%
      \edef\x{\endgroup
        \edef\noexpand#1{#1pt}%
      }%
    \x  
  \else
    \edef#1{\the#2}%
  \fi
}
\makeatother

\newcommand*{\blindtexttest}[1]{%
  Blindtext[#1]:
  \setbox\largebox\vbox{\blindtext[#1]}%
  \DefPositiveDimenValue\TotalHeight{\ht\largebox}%
  total height \TotalHeight\par
}

\begin{document}

\newcount\mytest
\mytest=0
\loop
  \advance\mytest by 1
  \blindtexttest{\the\mytest}
\ifnum\mytest<550\repeat

\end{document}

The values at the end and beyond the supported range:

Result

  • That's really very helpful to me! It works perfectly without any unwanted messages and I think it can be easily adapted for my target application. – Thomas F. Sturm Jul 6 '14 at 9:10

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.