# Center text in TikZ according to the text baseline, not the object itself

As a follow up to Adding TikZ code to TOC, I have a TikZ code added to each index entry. That code may contain these specific letters: A, N, C, P and Q. See the following example:

\documentclass{article}

\usepackage[titles]{tocloft}
\usepackage{tikz}

\newcommand*\info[1]{%
\begin{tikzpicture}
\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm] {\tt\scriptsize #1};
\end{tikzpicture}}

\newcommand{\listfoo}{List of foo}
\newlistof[section]{foo}{idf}{\listfoo}

\begin{document}

\refstepcounter{foo}

\refstepcounter{foo}

\listoffoo

\end{document}


As you can see, (pardon my possible misuse of the terms) both text objects are centralized, but the latter - because of the letter Q - does not look that aesthetic to me.

Since I know all the possible letters I may use, and as the only problematic letter is the Q, I wrote this fix using the xstring package and Martin Scharrer's suggestion:

\documentclass{article}

\usepackage[titles]{tocloft}
\usepackage{tikz}
\usepackage{xstring}

\newcommand*\info[1]{%
\begin{tikzpicture}
\IfSubStr{#1}{Q}{%
\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm] {\raisebox{\dimexpr-.5\height+.5\depth-.8ex\relax}{\tt\scriptsize #1}};}{%
\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm] {\tt\scriptsize #1};}
\end{tikzpicture}}

\newcommand{\listfoo}{List of foo}
\newlistof[section]{foo}{idf}{\listfoo}

\begin{document}

\refstepcounter{foo}

\refstepcounter{foo}

\listoffoo

\end{document}


That pretty much solves my issue.

I'd like to know if there are better ideas of how to solve this particular alignment issue, dynamically or not.

-

Using \raisebox is actually the right direction. However, in this case I would use its second optional argument to set the depth of the text to zero: \raisebox{0pt}[\height][0pt]{...}. This ignores everything below the baseline, while the text is actually not raised and the height stays like it is.

\documentclass{article}

\usepackage[titles]{tocloft}
\usepackage{tikz}
\usepackage{xstring}

\newcommand*\info[1]{%
\begin{tikzpicture}
\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm] {\tt\scriptsize\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}}

\newcommand{\listfoo}{List of foo}
\newlistof[section]{foo}{idf}{\listfoo}

\begin{document}

\refstepcounter{foo}

\refstepcounter{foo}

\refstepcounter{foo}

\listoffoo

\end{document}


You could also use the baseline={(<the node name>.base)} option to place the picture baseline to the text baseline. Then the framed text and not its frame is based at the same line as the other text. Finally, you can also move the baseline a little to adjust how the frame lies relative to the normal text: baseline={([yshift=<length>]<the node name>.base)}

\documentclass{article}

\usepackage[titles]{tocloft}
\usepackage{tikz}
\usepackage{xstring}

\newcommand*\info[1]{%
\begin{tikzpicture}[baseline={(TEXT.base)}]
\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm] (TEXT) {\tt\scriptsize\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}}

\newcommand{\listfoo}{List of foo}
\newlistof[section]{foo}{idf}{\listfoo}

\begin{document}

\refstepcounter{foo}

\refstepcounter{foo}

\listoffoo

\end{document}


-
It's a bit funny how it looks in the end better and worse at the same time. I think these boxes require font with all caps not (or only barely) crossing the baseline. Then box (after raising) will be able to fit within [baseline,cap height] and its bottom should lie on the baseline. This way weird look should be mostly dismissed. @Paulo: Maybe consider using TEX Gyre Cursor? – przemoc Jun 25 '11 at 23:39
Cool! I'll probably stick with the first one, since \raisebox sounds more semantic to me than the baseline option. Thanks a lot, Martin! – Paulo Cereda Jun 26 '11 at 10:42
@przemoc: Hm I didn't know that font, thanks for mentioning it! Unfortunately, for this particular case, this font will be out of style with the rest of the document. =) – Paulo Cereda Jun 26 '11 at 10:45

Another option would be to explicitly set text height and text depth:

\node[draw,inner sep=1pt, minimum height=0.32cm, minimum width=0.9cm,text height=0.6em,text depth=0.1em] {\ttfamily\scriptsize #1};

-
Cool, I didn't know of these parameters! I tried text centered, but since it didn't work, I gave up on trying anything else through TikZ. It's also a great solution, Gonzalo! Thanks! – Paulo Cereda Jun 26 '11 at 10:36

Say

{\smash[b]{\tt\scriptsize #1}}


instead of only {\tt\scriptsize #1} in the original definition. Requires amsmath.

-
Hm it's an interesting idea, egreg! Unfortunately, I can't use amsmath for this particular code, but I'll definitely save it for later. =) – Paulo Cereda Jun 26 '11 at 10:31