# Measure and retain lengths between tabular rows

I need elements in a tabular environment to set some lengths and be able to access these lengths in another row of this same table. But it appears that adding \global in front of \settoheight and \settowidth is not sufficient.

The the following MWE MeasureFigureAndPlaceFigure measures the height and width of the parameter passed to it, and attempts to globally set the lengths. This reports zero length and width after the tabular, but correct (ignoring the slight round off) lengths outside.

\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{printlen}
\uselengthunit{cm}

\newlength{\FigureHeight}
\newlength{\FigureWidth}
\newcommand{\MeasureFigureAndPlaceFigure}[1]{%
\global\settoheight{\FigureHeight}{#1}%
\global\settowidth{\FigureWidth}{#1}%
#1%
}%

\newcommand{\ReportHeightAndLength}{%
Width=\printlength{\FigureHeight}%
}%

\def\FigA{\includegraphics[width=2.0cm,height=1.0cm]{myimage}}

\begin{document}
\noindent% This reports 0 lengths
\begin{tabular}{@{}l@{}}
\MeasureFigureAndPlaceFigure{\FigA}
\end{tabular}
\ReportHeightAndLength

\noindent % This works just fine
\MeasureFigureAndPlaceFigure{\FigA}
\ReportHeightAndLength
\end{document}

-
\settowidth{\global\FigureWidth} should work. :) –  egreg Mar 1 '12 at 22:29
It does although relies on the internals of \settowidth. A fraction slower but perhaps less devious would be \settowidth{\dimen@}{...}\global\FigureWidth\dimen@ –  David Carlisle Mar 1 '12 at 22:34
Also there really isn't any need to typeset the figure three times just do \setbox\z@\hbox{#1}\global\FigureWidth\wd\z@\global\FigureHeight\ht\z@\box\z@ so you only set it once, save the dimensions then use the saved box. –  David Carlisle Mar 1 '12 at 22:38
@egreg: Yep that seems to be the answer. –  Peter Grill Mar 1 '12 at 22:42
@DavidCarlisle: Ok, the \setbox solution also work and I like it better as it seems less magical than \settowidth{\global\FigureWidth}, and more efficient. –  Peter Grill Mar 1 '12 at 22:45

\settowidth, \settoheight and \settodepth are defined via an auxiliary macro \@settodim:

\def\settoheight{\@settodim\ht}
\def\settodepth {\@settodim\dp}
\def\settowidth {\@settodim\wd}

\def\@settodim#1#2#3{\setbox\@tempboxa\hbox{{#3}}#2#1\@tempboxa
\setbox\@tempboxa\box\voidb@x}


Thus, \settowidth{\mylen}{Hello} is translated into

\@settodim\wd{\mylen}{Hello}


which in turn becomes

\setbox\@tempboxa\hbox{{Hello}}\mylen\wd\@tempboxa\setbox\@tempboxa\voidb@x


so that, after setting the box, TeX executes the assignment

\mylen=\wd\@tempboxa


and clears \@tempboxa (doing similarly for the other two macros).

From how the macros are defined we can deduce that

\settowidth{\global\mylen}{Hello}


will perform

\global\mylen=\wd\@tempboxa


which does what you want.

In case this is needed for more than a one shot hack it's probably better to define four "global" macros:

\makeatletter
\def\globalsettoheight{\@gsettodim\ht}
\def\globalsettodepth {\@gsettodim\dp}
\def\globalsettowidth {\@gsettodim\wd}

\def\@gsettodim#1#2#3{%
\setbox\@tempboxa\hbox{{#3}}\global#2#1\@tempboxa
\setbox\@tempboxa\box\voidb@x}
\makeatother


so that \globalsettowidth{\mylen}{Hello} will do the job with a more natural syntax.

For your specific application, you can define the new macro along these lines, but avoiding typesetting twice the box (as suggested by David Carlisle):

\newlength{\FigureHeight}
\newlength{\FigureWidth}
\newcommand{\MeasureFigureAndPlaceFigure}[1]{%
\setbox\@tempboxa\hbox{{#1}}%
\global\FigureHeight=\ht\@tempboxa
\global\FigureWidth\wd\@tempboxa
\box\@tempboxa
}

-