# funny interference between \baselinestretch and TikZ

The command \baselinestretch has a strange influence on Tikz Pictures, when it is not closed in a group (compare the two figures):

\documentclass[12pt]{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\end{tikzpicture}

\renewcommand{\baselinestretch}{2}

\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\end{tikzpicture}
\end{document}


I know that i should enclose the \baselinestretch in a group, but i found this effect funny ! :) (and i needed quite a long time to track this bug inside my documents...)

-
Note that adding \selectfont removes it! (thought I don't know why) Seriously, what is the question? –  ienissei Mar 27 '12 at 8:24
An the question ... is? –  Daniel Mar 27 '12 at 9:07
@nicolas roy: That is indeed a funny effect. It would be good if you could file a bug report at sourceforge.net/tracker/?group_id=142562&atid=752792. You can reduce the example to something like \documentclass{minimal} \usepackage{pgf} \begin{document} \renewcommand{\baselinestretch}{} \begin{pgfpicture} \pgfpathmoveto{\pgfpointorigin} \pgfpatharc{0}{180}{5cm} \pgfusepath{draw} \end{pgfpicture} \end{document}, which should produce a circular arc, but doesn't. –  Jake Mar 27 '12 at 9:12
@Daniel, @ienissei : well there is not exactly a question, since one should actually not use \baselinestretch in this way, but i think it shows that there is something strange in Tikz. On the other hand, this bug appear in a quite involved document class of mine, and i needed a long time to track it. So maybe if somebody encouters the same, he will know where to look for :) –  nicolas roy Mar 27 '12 at 9:22
To make it a question, one could ask for a temporary fix. –  Andrew Stacey Mar 27 '12 at 10:03

Experimenting, it would appear that during the tikzpicture, \baselinestretch should be equal to whatever it was when the \begin{document} command was issued. Moreover, it should not be long (no matter what \baselinestretch was at the start) - this is an issue with the article.cls since that contains the line \renewcommand{\baselinestretch}{} which makes it \long, whereas latex.ltx simply contains \def\baselinestretch{1} so is not \long. The fact that article.cls makes it long is irrelevant by the time one gets into the document since \selectfont has implicitly made it not long again.

So until the bug is squished, here's a work-around. I've tested it with various combinations of setting \baselinestretch with and without \long and it seems to survive them all, but as I don't really understand what's going on here I can't be held responsible for any damage caused by this strange behaviour.

\documentclass[12pt]{article}
\usepackage{tikz}
\AtBeginDocument{\let\tikzbaselinestretch\baselinestretch}
\tikzset{every picture/.append style={
execute at begin picture={%
\edef\baselinestretch{\tikzbaselinestretch}%
}
}
}

\begin{document}
\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\end{tikzpicture}

\renewcommand{\baselinestretch}{2}

\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\end{tikzpicture}
\end{document}


(Method incorporates suggestions from Jake, and experiments based on Altermundus' answer.)

Absolutely definitely a bug. But it's deep.

The bug is actually in \pgfmathsetlength. Quoting from the code:

Furthermore, the font is setup before the assignment is done, so that dimensions like 1em are evaluated correctly.

So within \pgfmathsetlength is a call to \pgfmath@selectfont. This is an alias of \selectfont (as we're using LaTeX) which calls \set@fontsize if \baselinestretch is not what it was the last time that \set@fontsize was called[1]. Then \set@fontsize executes \@defaultunits\@tempdimb#2pt\relax\@nnil. The upshot of is that if \baselinestretch has changed by some means other than a call to \set@fontsize then sometime in \pgfmathsetlength, \@tempdimb will get reassigned to something.

This, as Altermundus' hints at, causes problems for \pgfpatharc. Within that code is a call to \pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \pgfutil@tempdimb}. In processing this, PGF calls \pgfmathsetlength but it does so before looking at the \pgfutil@tempdima and \pgfutil@tempdimb part. So before we look at it, \pgfutil@tempdimb gets reassigned and we've forgotten what it originally was.

So the problem is that \pgfutil@tempdimb (which is an alias for @tempdimb) gets set to a new value before it is used. Exactly how to fix this properly, I'll leave to the PGF team! A simple solution would be that after loading TikZ (or PGF) one puts:

\makeatletter
\newdimen\pgfutil@tempdimb
\makeatother


This separates the link between \pgfutil@tempdimb and \@tempdimb at the expense of using up a dimen register. An alternative would be to hack \set@fontsize so that the assignment to \@tempdimb occurred in a group. Taking a leaf out of TikZ/PGF's many smuggling routines, we could do:

\def\set@fontsize#1#2#3{%
\bgroup
\@defaultunits\@tempdimb#2pt\relax\@nnil
\edef\@smuggle{{\edef\noexpand\f@size{\strip@pt\@tempdimb}}}%
\expandafter\aftergroup\@smuggle
\egroup
\@defaultunits\@tempskipa#3pt\relax\@nnil
\edef\f@baselineskip{\the\@tempskipa}%
\def\size@update{%
\baselineskip\f@baselineskip\relax
\normalbaselineskip\baselineskip
\setbox\strutbox\hbox{%
\vrule\@height.7\baselineskip
\@depth.3\baselineskip
\@width\z@}%
\let\size@update\relax}%
}


(I think that works without making any extra global assignments, but I'm no expert.)


-
In testing Altermundus' answer, I saw that it's the setting at the start of the document (\begin{document}) that matters, not what happens when TikZ is loaded. –  Andrew Stacey Mar 27 '12 at 11:00
I don't think that \long or non \long makes a difference, as this has only to do with what arguments the command can accept. –  egreg Mar 27 '12 at 11:58
@egreg: I bow to your superior expertise! All I can say is that when I experiment, then having \baselinestretch as \long or not makes a difference. My conjecture is that \baselinestretch is being compared with some "standard" and so that comparison fails if the \long/not\long match is wrong even if the value of the macro is correct. –  Andrew Stacey Mar 27 '12 at 12:01
Yes, inside \selectfont is \ifx\f@linespread\baselinestretch\else\set@fontsize ... \fi so there is a comparison of \baselinestretch with \f@linespread and \f@linespread is \edefed to the current \baselinestretch (no \long). –  Andrew Stacey Mar 27 '12 at 12:06
You're right, of course: I didn't think to that. This is a real LaTeX bug! Using \linespread instead of \renewcommand{\baselinestretch} would be safer. –  egreg Mar 27 '12 at 12:17

Perhaps the problem comes from

In latex.ltx there is

\def\set@fontsize#1#2#3{%
\@defaultunits\@tempdimb#2pt\relax\@nnil
\edef\f@size{\strip@pt\@tempdimb}%
\@defaultunits\@tempskipa#3pt\relax\@nnil
\edef\f@baselineskip{\the\@tempskipa}%


or in pgfutil-latex.def there is

\let\pgfutil@tempdima=\@tempdima
\let\pgfutil@tempdimb=\@tempdimb


and in pgfcorepathconstruct.code.tex

\def\pgf@arc{%
{%


Some Tex(perts) perhaps may confirm this hypothesis.

Update

The problem disappears if I redefine \def\pgf@arc{%

I replace \pgfutil@tempdimb by \mypgfutil@tempdimb

\documentclass[12pt]{article}

\usepackage{tikz}
\makeatletter
\newdimen\mypgfutil@tempdimb
\def\pgf@arc{%
{%
%
\pgf@xa=\pgf@arc@local@angle@a\relax%
\pgf@xb=\pgf@arc@local@angle@b\relax%
\ifdim\pgf@xb<0pt\relax%
\pgf@xb=-\pgf@xb\relax%
\fi%
\ifdim\pgf@xb=90.0pt%
\def\pgfmathresult{0.55228475}%
\else%
\pgfmathparse{1.333333333*tan(.25*\pgf@sys@tonumber{\pgf@xb})}% many thanks to Ken Starks
\fi%
\pgfutil@tempdima=\pgfmathresult\pgfutil@tempdima%
\mypgfutil@tempdimb=\pgfmathresult\mypgfutil@tempdimb%
%.. controls +(\pgf@xa+90:\pgfutil@tempdima) and +(\pgf@xb-90:\pgfutil@tempdima) .. +(-(#1:#3)+(#2:#3))%
% store first support vector in xa/ya:
\pgf@xa=\pgf@arc@local@angle@a\relax%
\ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax%
\else%
\fi%
\edef\pgf@arc@angle{\pgf@sys@tonumber{\pgf@xa}}%
\pgfpointtransformed{\pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \mypgfutil@tempdimb}}%
\pgf@xa=\pgf@path@lastx%
\pgf@ya=\pgf@path@lasty%
% store target in xb/yb:
\pgf@xb=\pgf@path@lastx%
\pgf@yb=\pgf@path@lasty%
% store second support xc/yc:
\ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax%
\else%
\fi%
\pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgfutil@tempdima and \mypgfutil@tempdimb}}%
\pgf@xc=\pgf@xb\relax%
\pgf@yc=\pgf@yb\relax%
\pgfsyssoftpath@curveto{\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xc}{\the\pgf@yc}{\the\pgf@xb}{\the\pgf@yb}%
\global\pgf@path@lastx=\pgf@xb%
\global\pgf@path@lasty=\pgf@yb%
\pgf@protocolsizes{\pgf@xa}{\pgf@ya}%
\pgf@protocolsizes{\pgf@xb}{\pgf@yb}%
\pgf@protocolsizes{\pgf@xc}{\pgf@yc}%
}%
}

\begin{document}
\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\node[draw,align=right]{azerty\\qwerty} ;
\end{tikzpicture}

I recommend the setspace package. That package provides commands (singlespacing,
onehalfspacing and doublespacing) and environments (singlespace, onehalfspace and
oublespace) that allow to change the spacing within the document. You will find the documentation inside the setspace.sty file. (Stefan)

\renewcommand{\baselinestretch}{2}

\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\node[draw,align=right]{azerty\\qwerty} ;
\end{tikzpicture}

I recommend the setspace package. That package provides commands (singlespacing,
onehalfspacing and doublespacing) and environments (singlespace, onehalfspace and
doublespace) that allow to change the spacing within the document. You will find the
documentation inside the setspace.sty file.  (Stefan)

\end{document}


Solution (workaround)


Then you can remark that inside the nodes the baselineskip is also changed.

Finally a good idea is to use the setspace package like Stefan writes on his blog !

\documentclass[12pt]{article}
\usepackage{setspace}
\usepackage{tikz}
%\renewcommand{\baselinestretch}{2}
\begin{document}
\begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\node[draw,align=right]{azerty\\qwerty} ;
\end{tikzpicture}

I recommend the setspace package. That package provides commands (singlespacing,


onehalfspacing and doublespacing) and environments (singlespace, onehalfspace and doublespace) that allow to change the spacing within the document. You will find the documentation inside the setspace.sty file. (Stefan)

  \doublespacing

I recommend the setspace package. That package provides commands (singlespacing,


onehalfspacing and doublespacing) and environments (singlespace, onehalfspace and doublespace) that allow to change the spacing within the document. You will find the documentation inside the setspace.sty file. (Stefan)

      \begin{tikzpicture}[scale = 2]
\draw[very thick] (2,-0.2)+(30:1cm) arc (30:150:1cm);
\node[draw,align=right]{azerty\\qwerty} ;
\end{tikzpicture}
\end{document}


-
Hypothesis 2/3rds confirmed. The first two were absolutely right, but the issue is not in \pgf@arc but in \pgfmathsetlength. –  Andrew Stacey Mar 27 '12 at 11:57
@AndrewStacey ok thanks to confirm the origin of evil ! –  Alain Matthes Mar 27 '12 at 12:26