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 would like to be able to scale text to the width of a TikZ node.

Using \widthof within tikzpicture as a starting point, I've arrived at somewhat of a solution, except it has incorrect spacing, and can probably be done more elegantly.

\documentclass{article}
\usepackage{tikz}
\usepackage{calc}
\usepackage{xstring}
\usepackage{ifthen}

\newlength{\scaleratio}

\makeatletter
\newcommand{\settowidthofnode}[2] {%
  \pgfextractx{#1}{\pgfpointanchor{#2}{east}}%
  \pgfextractx{\pgf@xa}{\pgfpointanchor{#2}{west}}%
  \addtolength{#1}{-\pgf@xa}%
}%
\makeatother

\makeatletter
\newcommand{\shrinktowidthofnode}[2] {%
  \settowidthofnode{\pgf@xb}{#2}%
  \setlength{\scaleratio} {%
    {1.0pt * \ratio{\pgf@xb}{\widthof{#1}}}%
  }%
  \ifthenelse{\lengthtest{\scaleratio < 1.0pt}} {%
    \setlength{\scaleratio}{\scaleratio}%
    \tokenize{\tokenized}{\the\scaleratio}%
    \StrBefore{\tokenized}{pt}[\result]%
    \scalebox{\result}{#1}%
  } {%
    #1%
  }%
}%
\makeatother

\begin{document}

\begin{tikzpicture}[every node/.style={draw,rectangle}]
  \draw[step=0.5cm,gray,very thin] (-3,-3) grid (3,3);
  \node (n) {blah};
  \node (m) [below of=n] {\shrinktowidthofnode{AAAAAAAA}{n}};
  \node (o) [below of=m] {\scalebox{0.43259}{AAAAAAAA}};
\end{tikzpicture}

\end{document}

The output looks like this:

Result

It's hard to see, but if you zoom in, the middle node's bounding box is larger than it should be, and there's some extra space on its left (there was more extra space earlier, but for some reason adding % to the end of each line in the \newcommands helped).

The bottom node is the ground truth. Any ideas?

share|improve this question
add comment

1 Answer 1

The east and west anchors include the inner margin between the text and the frame (inner sep). So you set your text as wide as the frame of the other node, not its text. Then the new node adds its own inner margin which makes it wider. I would use the text and center anchors instead (see pgfmanual page 420). They give you half the text width, so this must only be doubled.

There is also no need to use calc with tikz. It comes with its own math engine pgfmath which is more powerful. Also note that \pgfpointanchor (and all other \pgfpoint... macros) already stores the x-value into \pgf@x. The \pgfextractx just calls \pgf@process (which executes the \pgfpoint... macro locally and only makes the result global available) and set #1=\pgf@x.

In your case it's better to work with \pgf@x directly, just keep in mind that it will be overwritten by the next \pgfpoint... macro. Also there is no need to calculate the scale factor by yourself. Use \resizebox{<width>}{<height>}{<content>} from the graphics package (already loaded by pgf or tikz). Use a ! for the height here so that it scales accordantly to the width.

Now there seems to be an unwanted space inside either \pgfpointanchor or the anchor code itself which causes the extra white space before your AAAAAAAs. Adding \unskip after them fixes this. But this is worth investigating and to report it to the developers.

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand{\settowidthofnode}[2]{%
  \pgfpointanchor{#2}{center}%
  \unskip
  \setlength{#1}{\pgf@x}%
  \pgfpointanchor{#2}{text}
  \unskip
  \addtolength{#1}{-\pgf@x}%
  \addtolength{#1}{#1}%
}%
\newcommand{\shrinktowidthofnode}[2]{%
  \begingroup
  \settowidthofnode{\pgf@xb}{#2}%
  \resizebox{\pgf@xb}{!}{#1}%
  \endgroup
}%
\makeatother

\begin{document}

\begin{tikzpicture}[every node/.style={draw,rectangle}]
  \draw[step=0.5cm,gray,very thin] (-3,-3) grid (3,3);
  \node (n) {blah};
  \node (m) [below of=n] {\shrinktowidthofnode{AAAAAAAA}{n}};
  \node (o) [below of=m] {\scalebox{0.43259}{AAAAAAAA}};
\end{tikzpicture}

\end{document}

Result:

Result

share|improve this answer
    
This is beautiful and does exactly what I want, thank you very much. –  Greg Apr 8 '11 at 7:09
    
I accidentally finished the last comment and meant to add this: As a side comment, I've always felt helpless when it comes to latex. Say, for instance, I would like to know exactly what \unskip does, how would I go about doing that (google doesn't always work for this)? [I just made a CSE with several sites, hopefully that'll be useful] It looks like there are a few lines in pgfmoduleshapes.code.tex that need %s after them, however adding the %'s didn't seem to help (there's no compilation step for latex, is there?) possibly because several of the commands it uses are also lacking %s. –  Greg Apr 8 '11 at 7:31
    
How did you make the larger image? Ghostscript? Also, I just found out that code search indexes latex! –  Greg Apr 8 '11 at 7:38
    
@Greg: \unskip removes the last skip caused by the space and is a TeX primitive, i.e. a low level command. The %s add the end are most likely the cause (as always). I might have a look on it when I find time. The image was done by opening the PDF in Acrobat Reader, zooming and doing a screenshot. I just Shutter under Ubuntu Linux which allows me to select a rectangle area. –  Martin Scharrer Apr 8 '11 at 7:56
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.