\baselinestretch 和 TikZ 之间的有趣干扰

\baselinestretch 和 TikZ 之间的有趣干扰

\baselinestretch当 Tikz 图片未在组中关闭时,该命令对其有奇怪的影响(比较两个图):

\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}

我知道我应该将其括\baselinestretch在一个组中,但是我发现这种效果很有趣!:)(并且我需要很长时间才能在我的文档中追踪这个错误......)

答案1

经过实验,似乎在 tikzpicture 期间,\baselinestretch应该等于\begin{document}发出命令时的值。此外,它不应该很长(无论\baselinestretch开始时是什么)——这是article.clssince 包含\renewcommand{\baselinestretch}{}使其成为 的行的问题\long,而latex.ltx仅包含\def\baselinestretch{1}so 则不是。当进入文档时,使其变长\long这一事实无关紧要,因为已隐式地使其再次不长。article.cls\selectfont

因此,在错误被解决之前,这里有一个解决方法。我已经用各种设置组合测试了它,\baselinestretch似乎\long它都能生存下来,但由于我不太明白这里发生了什么,我不能对这种奇怪行为造成的任何损害负责。

\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}

(方法结合了 Jake 的建议和基于 Altermundus 的回答的实验。)


肯定是 bug。不过它很深奥。

这个错误实际上在\pgfmathsetlength。引用代码:

此外,字体在分配完成之前就已设置,因此可以正确评估 1em 之类的尺寸。

因此 within\pgfmathsetlength是对 的调用\pgfmath@selectfont。这是 的别名\selectfont(因为我们使用的是 LaTeX),它调用\set@fontsizeif\baselinestretch不是上次\set@fontsize调用时的值[1]。然后\set@fontsize执行\@defaultunits\@tempdimb#2pt\relax\@nnil。结果是 if\baselinestretch以某种方式发生了变化其他\set@fontsize比在某个时间对 的调用\pgfmathsetlength\@tempdimb将被重新分配给某个东西。

正如 Altermundus 所暗示的,这会导致 出现问题\pgfpatharc。该代码中有一个对 的调用\pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \pgfutil@tempdimb}。在处理此代码时,PGF 会调用\pgfmathsetlength但它确实这样做了看看这个\pgfutil@tempdima and \pgfutil@tempdimb部分。所以在我们看之前,它\pgfutil@tempdimb被重新分配了,我们已经忘记了它原来是什么。

因此,问题在于\pgfutil@tempdimb(的别名@tempdimb)在使用之前被设置为新值。如何正确修复此问题,我将留给 PGF 团队!一个简单的解决方案是,在加载 TikZ(或 PGF)后,输入:

\makeatletter
\newdimen\pgfutil@tempdimb
\makeatother

这会以占用 dimen 寄存器为代价来分离\pgfutil@tempdimb和之间的链接。另一种方法是进行破解,以便将分配给一个组。借鉴 TikZ/PGF 的许多走私程序,我们可以这样做:\@tempdimb\set@fontsize\@tempdimb

\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}%
    \edef\f@linespread{#1}%
    \let\baselinestretch\f@linespread
      \def\size@update{%
        \baselineskip\f@baselineskip\relax
        \baselineskip\f@linespread\baselineskip
        \normalbaselineskip\baselineskip
        \setbox\strutbox\hbox{%
          \vrule\@height.7\baselineskip
                \@depth.3\baselineskip
                \@width\z@}%
        \let\size@update\relax}%
  }

(我认为这无需进行任何额外的全局分配即可,但我不是专家。)

[1] 稍长一点的形式是,\set@fontsize将 的当前值保存\baselinestretch为宏\f@linespread(不是\long),然后\let将 添加\baselinestretch到此宏中。因此,调用 之后\set@fontsize\baselinestretch保证\f@linespread相同。如果\baselinestretch在此期间有人干扰 ,即使只是\renewcommand\baselinestretch{whatever it currently is},那么此比较也会失败并\set@fontsize再次被调用。在本例中,\baselinestretch已经 被执行,\long因为我没有执行\renewcommand*

答案2

也许问题来自于

在 latex.ltx 中有

\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}%

或者在 pgfutil-latex.def 中有

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

并在 pgfcorepathconstruct.code.tex 中

\def\pgf@arc{%
  {%
  \pgfutil@tempdima=\pgf@arc@radius@a pt%
  \pgfutil@tempdimb=\pgf@arc@radius@b pt%

一些 Tex(perts) 也许可以证实这一假设。

更新

如果我重新定义,问题就会消失\def\pgf@arc{%

\pgfutil@tempdimb替换\mypgfutil@tempdimb

\documentclass[12pt]{article}  

\usepackage{tikz} 
\makeatletter
\newdimen\mypgfutil@tempdimb
\def\pgf@arc{%
  {%
  \pgfutil@tempdima=\pgf@arc@radius@a pt%
  \mypgfutil@tempdimb=\pgf@arc@radius@b pt%
  %
  \pgf@xa=\pgf@arc@local@angle@a\relax% 
  \pgf@xb=\pgf@arc@local@angle@b\relax%
  \advance\pgf@xb by-\pgf@xa\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%
    \advance\pgf@xa by 90pt\relax%
  \else%
    \advance\pgf@xa by -90pt\relax%
  \fi%
  \edef\pgf@arc@angle{\pgf@sys@tonumber{\pgf@xa}}%  
  \pgfpointtransformed{\pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \mypgfutil@tempdimb}}%
  \advance\pgf@x by-\pgf@pt@x%
  \advance\pgf@y by-\pgf@pt@y%
  \pgf@xa=\pgf@path@lastx%
  \pgf@ya=\pgf@path@lasty%
  \advance\pgf@xa by \pgf@x%
  \advance\pgf@ya by \pgf@y%
  % store target in xb/yb:
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@a}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}%
  \pgf@xb=\pgf@path@lastx%
  \pgf@yb=\pgf@path@lasty%
  \advance\pgf@xb by -\pgf@x%
  \advance\pgf@yb by -\pgf@y%
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}%
  \advance\pgf@xb by \pgf@x%
  \advance\pgf@yb by \pgf@y%
  % store second support xc/yc:
  \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax%
    \advance\pgf@arc@local@angle@b by -90pt\relax%
  \else%
    \advance\pgf@arc@local@angle@b by 90pt\relax%
  \fi%
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgfutil@tempdima and \mypgfutil@tempdimb}}%
  \advance\pgf@x by-\pgf@pt@x%
  \advance\pgf@y by-\pgf@pt@y%
  \pgf@xc=\pgf@xb\relax%
  \pgf@yc=\pgf@yb\relax%
  \advance \pgf@xc by \pgf@x\relax%
  \advance \pgf@yc by \pgf@y\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}

解决方案(解决方法)

\renewcommand{\baselinestretch}{2}首先,如果你在序言中使用,则没有问题。从逻辑上讲,我还没有测试过,但\renewcommand{\baselinestretch}{2}如果你想进行本地更改,也许你可以在组中使用。

然后你可以注意到节点内部的baselineskip也发生了变化。

最后一个好主意是使用 setspace 包,就像 Stefan 在他的博客上写的那样!

\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, 

允许更改文档内间距的 10 个环境(onehalfspacing 和 doublespacing)和环境(singlespace、onehalfspace 和 doublespace)。您可以在 setspace.sty 文件中找到相关文档。(Stefan)

  \doublespacing

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

允许更改文档内间距的 10 个环境(onehalfspacing 和 doublespacing)和环境(singlespace、onehalfspace 和 doublespace)。您可以在 setspace.sty 文件中找到相关文档。(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} 

在此处输入图片描述

相关内容