6

I want to find the width that a node will have when it is later constructed. The width depends on the node's content and the style applied to the node. The style may alter the font using the font key.

My attempt was to use \settowidth on a TikZ picture containing just the node, with the style applied but inner sep set to zero. This works fine if the style used is something like red or text opacity=.1 or, even,fill=colour@background. But if the user adds font=\scriptsize to the style, then compilation fails with a fatal error.

MNWE:

\documentclass[border=10pt,multi,tikz]{standalone}
\newlength\mylength
\tikzset{%
  my code/.code={%
    \settowidth\mylength{\tikz{\node[my style] {something};}}%
    \draw (0,0) -- +(\mylength,0);
  },
  my style/.style={red},
}
\begin{document}
\begin{tikzpicture}
  [
    my code,
  ]
\end{tikzpicture}
\begin{tikzpicture}
  [
    my style/.style={font=\normalfont},% or font=\scriptszie or font=\itshape or whatever
    my code,
  ]% this is line 119 mentioned in the error message
\end{tikzpicture}
\end{document}

Here's the error in all its lethal glory:

! TeX capacity exceeded, sorry [input stack size=5000].
\pgf@selectfontorig ->\pgf@selectfontorig 
                                          \nullfont 
l.119   ]

!  ==> Fatal error occurred, no output PDF file produced!

Now \nullfont looks clearly dodgy, but I'm not sure why TikZ would be falling through to it.

In any case, my approach is clearly far too simple-minded.

What is the cause of the error and how can it be avoided?

  • 1
    If I just do \settowidth{\node ...} I don't get errors, but is that really correct? – cfr Aug 15 '16 at 1:19
  • 1
    I get a width of zero, of course, regardless of content, so I could just as well use 0pt and be done with it ;). – cfr Aug 15 '16 at 1:29
  • 1
    In a tikzpicture, outside of nodes, the default font is \nullfont (cf. p.124, pgfmanual v3.0.1a). – Paul Gaborit Aug 15 '16 at 8:33
4

You may use the calc library and a very distant scope with overlay key:

enter image description here

enter image description here

\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{calc}
\tikzset{%
  my code/.code={%
    \begin{scope}[overlay]
      \node[my style,anchor=west] (a) at (-16000pt,0) {something};
      \path let \p1 = (a.east), \p2 = (a.west), \n1 = {veclen(\x2-\x1,0)}
      in \pgfextra{\xdef\mygloballenght{\n1}};
    \end{scope}
    \draw[black] (0,0) -- +(\mygloballenght,0);
  },
}
\begin{document}
\begin{tikzpicture}[my style/.style={red,font=\Large}]
  \draw[red] (0,1) -- (2,1);
  \tikzset{my code}
\end{tikzpicture}
\begin{tikzpicture}[my style/.style={font=\normalfont}]
  \draw[red] (0,1) -- (2,1);
  \tikzset{my code}
\end{tikzpicture}
\end{document}
| improve this answer | |
  • Thanks you! Could you explain why veclen is needed? Why isn't this just like using \x2-\x1? Do you by any chance know why the manual says it is possible to 'escape back' to normal typesetting but then fails to say anything about how to do so?! – cfr Aug 15 '16 at 12:08
  • @cfr I use veclen to not to pay attention to the sign...! You may escape back by using carefully the pgfinterruptpicture environment. – Paul Gaborit Aug 15 '16 at 13:21
  • Not abs()? Or does that not work with dimensions? Thanks. – cfr Aug 15 '16 at 14:41
  • @cfr abs is another solution (because, here, the second coordinate is zero). – Paul Gaborit Aug 15 '16 at 15:16
  • Thanks again. Just wanted to make sure I wasn't missing something. (I never use veclen. I do use abs, I guess.) pgfinterruptpicture is interesting. – cfr Aug 15 '16 at 22:28

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.