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'm trying to use an \hbox to measure the dimensions of a certain text. This is working in normal text as in the following example:

\setbox37=\hbox{this is a text that I want to measure}
text width is \the\wd37, text heigh is \the\ht37\\
text contents: \box37

The output is correct as I expected:

text width is 159.63913pt, text heigh is 6.94444pt
text contents: this is a text that I want to measure

However, when trying to do the same inside a TikZ environmnet, the box I'm using is not assigned the text I pass to \hbox, instead I gets empty box with zero width & height. Here is the code:

\begin{tikzpicture}
  \setbox37=\hbox{this is a text that I want to measure}
  \node[draw] at (0,0) {text width is \the\wd37, text heigh is \the\ht37};
  \node[draw] at (0,-1) {text contents is \box37};
\end{tikzpicture}

And here is the output:

output

What am I missing here?

share|improve this question

1 Answer 1

up vote 15 down vote accepted

PGF/TikZ takes care that non-drawing material inside its picture environments is not typeset. The whole environment is stored in a box which is later discarded while (IMHO) the drawing commands draw in a different box which is then typeset. This alone wouldn't be an issue for your code, but PGF/TikZ also sets the font to \nullfont as well redefines \selectfont to suppress font changes. Only for node contents and other "official" text like labels the font is restored.

Therefore the text in your box can't be typeset and the box is empty. A trace with \tracingall gives you the following messages:

{\setbox}
{the letter t}
Missing character: There is no t in font nullfont!
{the letter h}
Missing character: There is no h in font nullfont!
{the letter i}
...

You need to either set the box outside the picture environment or restore the font. You can use the pgfinterruptpicture environment to escape to a normal typesetting state with font.

\documentclass{article}
\usepackage{tikz}

\newbox\mybox

\begin{document}
\begin{tikzpicture}
  \setbox\mybox=\hbox{\pgfinterruptpicture this is a text that I want to measure\endpgfinterruptpicture}
  \node[draw] at (0,0) {text width is \the\wd\mybox, text heigh is \the\ht\mybox};
  \node[draw] at (0,-1) {text contents is \box\mybox};
\end{tikzpicture}
\end{document}

Alternatively you could restore \selectfont and the font manually just for the box content:

\documentclass{article}
\usepackage{tikz}

\newbox\mybox
\let\origselectfont\selectfont
\newcommand{\restorefont}{%
    \let\selectfont\origselectfont
    \normalfont
}
\begin{document}
\begin{tikzpicture}
  \setbox\mybox=\hbox{\restorefont this is a text that I want to measure}
  \node[draw] at (0,0) {text width is \the\wd\mybox, text heigh is \the\ht\mybox};
  \node[draw] at (0,-1) {text contents is \box\mybox};
\end{tikzpicture}
\end{document}

Some other notes:

  • You shouldn't use plain numbers for boxes. Box #37 might be used by some other code. My first guess was that TikZ uses it and sets it to be empty :-)
  • AFAIK with the \setbox primitive there might be issues with color changes. Use \sbox\mybox{<content>} instead which handles them.
share|improve this answer
    
Thanks for explaining the reason; I knew how to solve the problem using \global\setbox but didn't know why it was necessary to do so. –  Gonzalo Medina May 19 '11 at 14:59
    
@Martin thanks for the explanation. using pgfinterruptpicture works for me. –  John Kirollos May 19 '11 at 16:09
    
@John: You are welcome. Please always also up-vote the answers you accept. –  Martin Scharrer May 19 '11 at 16:17
    
I find it miraculous that this problem, which I thought was too obscure to ever have been asked, has not only been asked but been answered so well (and just one month ago). –  Ryan Reich Jun 21 '11 at 17:12
    
Also, the PGF manual says that {pgfinterruptpicture} is intended for use inside a box. If you put it there, you no longer need to use \global (I tested this and it works). –  Ryan Reich Jun 21 '11 at 17:23

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.