4

I do not know if this is expected or not; this is probably a very dumb operator error, but consider the following MWE:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\pgfdeclareshape{sline}{
    \anchor{center}{\pgfpointorigin}%
    \behindbackgroundpath{
        % \pgfsetcolor{.}%       <- line B
        % \pgfsetfillcolor{red}% <- line A
        \pgfpathmoveto{\pgfpoint{-0.3cm}{0pt}}%
        \pgfpathlineto{\pgfpoint{0.3cm}{0pt}}%
        \pgfnode{circle}{center}{}{}{\pgfusepath{stroke,fill}}%
        \pgftext[top,y=0.4cm]{zzz}%
        \pgfusepath{draw}%
    }
}
\begin{document}
Text
\begin{tikzpicture}[]
    \draw[] (0,1)  node [sline]{} (1,1) node{aaa};
    \draw[blue, fill=green] (0,0)  node [sline]{} (1,0) node{aaa};
\end{tikzpicture}
\end{document}

Which result in:

enter image description here

What is quite puzzling is the fact that "zzz" is following the fill color of the shape and not the stroke color. I tried to find something in the manual, to no avail.

What I would like is that the shape could follow the external "fill" parameter (either in the draw, or in the shape itself) but the text should follow the draw color, like "aaa" is doing (or at least following the external current color).

Uncommenting line B gives the "fill and stroke as the current color", as expected (\pgfsetcolor sets both stroke and fill):

enter image description here

...and uncommenting both line A and line B gives a fixed red fill and red text.

enter image description here

Commenting just line B gives:

enter image description here

In conclusion, it seems that the text created by \pgftext is colored with the fill color and colored with the current color only if the fill color is undefined. Is this the expected behavior?

2
  • Both \pgftext and normal text are colored with the fill color. You can play with this pdf literal example: \Huge text \pdfliteral page{q 2 Tr 1 0 0 rg 0 1 0 RG .5 w}text\pdfliteral page{Q} text. Here 2 Tr sets the rendering mode to "fill, then stroke text" (the default is fill only), 1 0 0 rg sets the fill color red, and 0 1 0 RG sets the stroke color green. Feb 22, 2022 at 18:32
  • @muzimuzhiZ thanks --- one always learns something new. So I suppose I will have to scope the \pgftext setting locally the color to the default one... is there something as \pgf@textcolor defined if the user says node[blub, text=red]?
    – Rmano
    Feb 22, 2022 at 19:05

1 Answer 1

4
+50
  • In principal, text is colored with fill color, not stroke color. After all, modern fonts are all outline fonts. Commands like \color and \textcolor set both the fill and stroke color, making the fact that "text is filled" less imperceptible.

  • Therefore in pgf, each of \pgftext, \pgfnode, and \pgfmultipartnode colors the (node) text with current fill color.

  • But tikz introduces a new concept "text color" which is set by text=<color> and init to empty per node. If set, for node text both the current fill and stroke color are locally set to the text color. The related code is in \tikz@do@fig:

    \ifx\tikz@textcolor\pgfutil@empty%
    \else%
       \pgfutil@colorlet{.}{\tikz@textcolor}%
       \pgfutil@color{\tikz@textcolor}%
    \fi%
    

    A slightly different logic can be found in \tikz@nodepart@continue and \tikz@fig@continue which uses \pgfsetcolor{.} after \fi instead of \pgfutil@color{\tikz@textcolor}. The differences I know by far is that \pgfsetcolor will also set named colors pgfstrokecolor and pgffillcolor.

  • Therefore, through tikz options, one can use up to three different colors for a node:

    \node[draw=blue, fill=yellow!20, text=cyan] {text};
    
  • Back to pgf layer, some manual work is needed since option text=<color> is only available in tikz layer and the above code logic is only applied to tikz (not pgf) node text.

The example below provides a \pgf@cir@usetextcolor that sets the current fill and stroke color to text color if the latter is set.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{sline}{
    \anchor{center}{\pgfpointorigin}%
    \behindbackgroundpath{
        % \pgfsetcolor{.}%       <- line B
        % \pgfsetfillcolor{red}% <- line A
        \pgfpathmoveto{\pgfpoint{-0.3cm}{0pt}}%
        \pgfpathlineto{\pgfpoint{0.3cm}{0pt}}%
        \pgfnode{circle}{center}{}{}{\pgfusepath{stroke,fill}}%
        \pgfusepath{draw}
        % \pgfscope
        \pgf@circ@usetextcolor % if used at last, no need to wrap in pgfscope
        \pgftext[top,y=0.4cm]{zzz}%
        % \endpgfscope
    }
}

\def\pgf@circ@usetextcolor{%
  \ifx\tikz@textcolor\pgfutil@empty
  \else
    \pgfutil@colorlet{.}{\tikz@textcolor}%
    \pgfutil@color{\tikz@textcolor}%
  \fi
}
\makeatother

\begin{document}
Text
\begin{tikzpicture}[]
    \draw[] (0,1)  node [sline]{} (1,1) node{aaa};
    \draw[blue, fill=green] (0,0)  node [sline]{} (1,0) node{aaa};
    \draw[blue, fill=green] (0,-1)  node [sline,text=red]{} (1,-1) node[text=red]{aaa};
\end{tikzpicture}
\end{document}

enter image description here

3
  • Impressive answer +1
    – SebGlav
    Feb 22, 2022 at 22:49
  • @SebGlav Hi, answer updated to correct some mistakes in explanation. Feb 23, 2022 at 0:04
  • Thanks! In my case, it will be simpler because I do not really want the text in \pgftext to follow the text color, but the stroke color --- it's basically the numbering of pins or polarity, etc. so they are logically part of the shape "contour".
    – Rmano
    Feb 23, 2022 at 9:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .