Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

enter image description here

\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}{%
    Height=\printlength{\FigureHeight}\quad%
    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}
share|improve this question
2  
\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
1  
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
add comment

1 Answer

up vote 6 down vote accepted

\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
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.