5

The below MWE draws a number of rectangles using low-level pgf commands, each specified with a different unit that Latex understands. However, pgf doesn't seem to be able to determine the relative units ex, em and sp. Is there a reason for that?

By way of context, I was trying to declare a new shape with a size relative to the current text. As the shape isn't meant to contain any text, it seemed a better approach than making it relative to a non-existent \pgfnodeparttextbox. If pgf can't cope with relative units in this context, is there a better approach to setting the initial size of a shape?

Boxes drawn with different units in pgf

\documentclass[a4paper]{article}
\usepackage{tikz}

\begin{document}

\newdimen\ptdim
\newdimen\pcdim
\newdimen\indim
\newdimen\bpdim
\newdimen\cmdim
\newdimen\mmdim
\newdimen\dddim
\newdimen\ccdim
\newdimen\spdim
\newdimen\exdim
\newdimen\emdim

\begin{tikzpicture}
  \ptdim=12pt
  \pcdim=2pc
  \indim=2in
  \bpdim=100bp
  \cmdim=3cm
  \mmdim=20mm
  \dddim=40dd
  \ccdim=10cc
  \spdim=500sp
  \exdim=5ex
  \emdim=5em
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\ptdim}{\ptdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\pcdim}{\pcdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\indim}{\indim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\bpdim}{\bpdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\cmdim}{\cmdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\mmdim}{\mmdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\dddim}{\dddim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\ccdim}{\ccdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\spdim}{\spdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\exdim}{\exdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\emdim}{\emdim}}
  \pgfusepath{stroke}
  \node[below] at (\ptdim,0) {pt};
  \node[below] at (\pcdim,0) {pc};
  \node[below] at (\indim,0) {in};
  \node[below] at (\bpdim,0) {bp};
  \node[below] at (\cmdim,0) {cm};
  \node[below] at (\mmdim,0) {mm};
  \node[below] at (\dddim,0) {dd};
  \node[below] at (\ccdim,0) {cc};
  \node[below] at (\spdim,0) {sp};
  \node[below] at (\exdim,0) {ex};
  \node[below] at (\emdim,0) {em};
\end{tikzpicture}
\end{document}
ThomasH
  • 942

2 Answers2

10

In a TikZ picture, the current font is set to \nullfont, generally, in order to avoid casual typesetting; this font has all parameters equal to zero, so 1em = 1ex = 0pt when the font is \nullfont. On the other hand, 1sp is very small, because 65536sp=1pt, so it's almost impossible to appreciate a displacement by 500sp.

Just set the lengths before entering the picture:

\documentclass[a4paper]{article}
\usepackage{tikz}

\begin{document}

\newdimen\ptdim
\newdimen\pcdim
\newdimen\indim
\newdimen\bpdim
\newdimen\cmdim
\newdimen\mmdim
\newdimen\dddim
\newdimen\ccdim
\newdimen\spdim
\newdimen\exdim
\newdimen\emdim

  \ptdim=12pt
  \pcdim=2pc
  \indim=2in
  \bpdim=100bp
  \cmdim=3cm
  \mmdim=20mm
  \dddim=40dd
  \ccdim=10cc
%  \spdim=500sp
  \exdim=5ex
  \emdim=5em
\begin{tikzpicture}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\ptdim}{\ptdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\pcdim}{\pcdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\indim}{\indim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\bpdim}{\bpdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\cmdim}{\cmdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\mmdim}{\mmdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\dddim}{\dddim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\ccdim}{\ccdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\spdim}{\spdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\exdim}{\exdim}}
  \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{\emdim}{\emdim}}
  \pgfusepath{stroke}
  \node[below] at (\ptdim,0) {pt\vphantom{pb}};
  \node[below] at (\pcdim,0) {pc\vphantom{pb}};
  \node[below] at (\indim,0) {in\vphantom{pb}};
  \node[below] at (\bpdim,0) {bp\vphantom{pb}};
  \node[below] at (\cmdim,0) {cm\vphantom{pb}};
  \node[below] at (\mmdim,0) {mm\vphantom{pb}};
  \node[below] at (\dddim,0) {dd\vphantom{pb}};
  \node[below] at (\ccdim,0) {cc\vphantom{pb}};
%  \node[below] at (\spdim,0) {sp};
  \node[below] at (\exdim,-0.5) {ex\vphantom{pb}};
  \node[below] at (\emdim,-0.5) {em\vphantom{pb}};
\end{tikzpicture}
\end{document}

enter image description here

egreg
  • 1,121,712
  • +1 for the in-depth explanation. I misread sp in Stefan's answer, it seems. I thought it's 65.536 sp = 1 pt, not 65000 ... – ThomasH Mar 27 '13 at 21:19
  • @ThomasH I removed the misleading comma from that answer. – egreg Mar 27 '13 at 21:25
  • 2
    Just to note: it would be alright to put the lengths in directly (\pgfpathrectangle{\pgfpointorigin}{\pgfpoint{1em}{1em}}) or to use PGFMath to set the lengths (\pgfmathsetlength\emdim{1em}) because when PGF computes a length itself then it restores the current font to get such lengths right. The problem with the original post is that it doesn't use PGF's methods for setting lengths but uses TeX's methods directly and so PGF doesn't get a chance to undo the \nullfont declaration. – Andrew Stacey Mar 27 '13 at 22:53
1

Try doing the following

\setlength{\exdim}{5ex}
\setlength{\emdim}{5em}

It seems to work for me.

A.Ellett
  • 50,533