选项(绘制和字体)、pgfextra 和 TikZ 路径上节点的执行顺序

选项(绘制和字体)、pgfextra 和 TikZ 路径上节点的执行顺序

这是关于 TikZ 路径上选项、pdfextra 代码和其他元素的执行顺序的第三篇也是最后一篇帖子。其他帖子是

请考虑以下 LaTeX 手稿

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \def\x{outside}

        \path[draw=blue,font=\Huge]

                 \pgfextra{  \def\x{inside}
                             \draw (2,2) circle(5pt)
                                   node[anchor=south west]{xtra};}

                 (0,0) node[draw] {\x}
         ;
    \end{tikzpicture}
\end{document}

手稿中有一张 TikZ 图片。图片内部执行的第一个操作是将 TeX 宏定义\x为字符串“outside”。然后定义一个 TikZ 路径,其中包含两个选项:绘制颜色设置为“blue”,字体大小设置为“\Huge”。路径由两个元素组成:(1)一个\pgfextra块。该块将宏重新定义\x为字符串“inside”。然后它绘制一个圆圈,旁边是一个显示文本为“xtra”的节点。(2)显示文本为\x替换文本的节点。绘制节点的轮廓。

本稿排版如下:

                                         第一份手稿

请注意,路径的font选项既适用于\pdfextra代码也适用于节点,但draw选项仅适用于节点。为什么?

回答这个问题的一个可能的理论是,无论出于什么原因,代码按以下顺序执行:1.font选项,2. \pdfextra,3.draw选项,4.节点。

\pgfextra让我们通过将元素移动到节点后面来测试这个理论:

\path[draw=blue,font=\Huge]

     (0,0) node[draw] {\x}

     \pgfextra{  \def\x{inside}
                 \draw (2,2) circle(5pt)
                 node[anchor=south west]{xtra};}
     ;

我期望节点的显示文本为“外部”,圆的描边颜色为蓝色。然而,我只猜对了一部分:

                                         第二份手稿

答案1

如果你查看源代码,你会发现在路径上遇到tikz.code.tex时执行的代码的定义:\pgfextra

\def\tikz@extra{\pgfutil@ifnextchar\bgroup\tikz@@extra\relax}
\long\def\tikz@@extra#1{#1\tikz@scan@next@command}
\let\endpgfextra=\tikz@scan@next@command

基本上,任何参数都会\pgfextra立即执行,扫描继续。不会保存或恢复任何图形或字体属性。

当执行如下操作时:

\path [...properties1...] ... \pgfextra { \path [] ...; };

已设置的任何属性properties1 可以不可以影响内部的路径\pgfextra。这取决于属性、何时设置、是否全局设置,以及可能还有一些我没有想到的其他事情。

考虑基本节点字体(即用于排版节点的字体)。它存储在\tikz@textfont全局中,并最初(有效地)分配如下:

\let\tikz@textfont=\pgfutil@empty

因此它不包含任何值。这意味着节点中的任何文本都将采用文档字体。当font使用键时(例如font=\Huge),将执行以下键:

\tikzoption{font}{\def\tikz@textfont{#1}}

现在,\tikz@textfont包含\Huge并且任何没有特定字体的节点都将使用此值在当前范围内。当font在节点中使用键时,其值将“保留”到节点结束。但是当font在路径中使用键时,其值将保留到路径结束。任何未指定字体的节点都应采用此值。但是,对于嵌入在路径中的树或图形等内容,这种情况可能会发生,也可能不会发生(如果它们设置了范围并重置了字体,则可能不会)。

这仅适用于字体。线条宽度、颜色等可能有所不同。PGF 已实施多年,参与人员也各不相同。由于以下原因,可能会存在一些一致性,也可能存在一些不一致性:

  1. 特定功能需要不同的功能
  2. 对应该发生的事情有强烈的感觉
  3. 对已经发生的事情的误解
  4. 我还没有想到的其他一些事情

最重要的是这些都不重要

首先,\pgfextra它不是为任意代码设计的。它会立即执行,而不会考虑图形或字体属性可能发生或不会发生什么。特别是,随意地塞入内部\path而不\pgfextra使用\pgfinterruptpath会导致未定义的行为,在这种情况下,一致性的期望有点令人困惑。

其次,即使\pgfinterruptpath使用了,并且一些属性是继承的而一些属性不是,明确地设置内部任何路径的属性\pgfextra并不难,特别是因为多个属性可以与样式绑定。

答案2

以下示例说明了为什么您的问题几乎总是无法用简单的参数来回答。此示例具有扩展延迟,因此我们在放置节点后会更改其颜色。这在通常的语法中是不可能的,但在滥用和黑客攻击下却有可能。

\documentclass{article}
\usepackage{tikz}
\def\mymacro{\expandafter\global\expandafter\let\expandafter\pgfsavedstrokecolor\csname\string\color@pgfstrokecolor\endcsname}
\begin{document}
\begin{tikzpicture}
\path[draw=blue,font=\Huge]
     \pgfextra{
     \def\x{inside}\mymacro\show\pgfsavedstrokecolor% <-- look at the log it's black again 
     \expandafter\show\csname tikz@strokecolor\endcsname% <-- this one is still blue
     \draw (2,2) circle(5pt)%
     node[draw,anchor=south west]{xtra}
     % we'll change the color of the node above to red with the next line!!
     \pgfextra{\csname tikz@addoption\endcsname{\pgfsetstrokecolor{red}}}
     node[draw]{xtra2}; %<-- draws red
     }
     (0,0) node[draw] {\x};
\end{tikzpicture}
\end{document}

在此处输入图片描述

除了这个黑魔法之外,如果你注释掉最后一个,\pgfextra它们都是不是蓝色而是黑色。不是因为一个 bug!但因为我们的 hack 省略了一半正常工作所需的宏。这就是你一直在做的事情,而且让你感到困惑。有太多宏需要设置/重置来模仿 TikZ 行为。

总之,如果不采取极端预防措施(例如适当的 TeX 组和扩展控制),您就不能指望事情在低级别上正常工作。这就是 TikZ 前端的整个想法,这样您就不需要自己做这些了。在路径中间暂停并做一些不平凡的事情需要 TeX 知识,这通常超出了我的能力范围,并且需要正确的 PDF 文字顺序。否则,您会得到如上所述的巫术魔法。

简而言之,事情并不是那么简单的理论,正如评论所说,直到最后事情才完全展开,才有执行顺序。

相关内容