[Tex/LaTex] How to retrieve current stroke and fill color in PGF/TikZ

colortikz-pgf

I am defining a shape which can be drawn in normal or inverted mode. In normal mode, the border lines and inner lines are drawn with the current stoke color, while the shape is filled with the current fill color. In inverted mode, the border lines is still drawn with the current stoke color, but the shape is filled with the current stroke color and inner lines are drawn with the current fill color.

Here is a MWE:

\documentclass[varwidth,border=50]{standalone}

\usepackage{tikz}

\makeatother

\pgfkeys{%
  /pgf/invert/.initial=no,%
  /pgf/invert/.default=yes,%
}

\pgfdeclareshape{test}{%
  \inheritsavedanchors[from=circle]%
  \inheritanchorborder[from=circle]%
  \inheritanchor[from=circle]{center}%
  %
  \backgroundpath{%
    \pgfpathcircle{\pgfpointorigin}{5em}%
  }%
  %
  \beforebackgroundpath{%
    %\def\strokecolor{\string\color@pgfstrokecolor}%
    %\def\fillcolor{\string\color@pgffillcolor}%
    %\global\let\strokecolor\csname\string\color@pgfstrokecolor\endcsname%
    %\global\let\fillcolor\csname\string\color@pgffillcolor\endcsname%
    \def\borderColor{\strokecolor}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
      \def\fillColor{\fillcolor}%
      \def\innerColor{\strokecolor}%
    \else%
      \def\fillColor{\strokecolor}%
      \def\innerColor{\fillcolor}%
    \fi%
    \pgfsetlinewidth{.5em}%
    \pgfsetstrokecolor{\borderColor}%
    \pgfsetfillcolor{\fillColor}%
    \pgfpathcircle{\pgfpointorigin}{5em}%
    \pgfusepath{fill,stroke}%
    \pgfsetstrokecolor{\innerColor}%
    \pgfmoveto{\pgfpointpolar{135}{4em}}%
    \pgflineto{\pgfpointpolar{-45}{4em}}%
    \pgfusepath{stroke}%
  }%
}

\makeatletter

\begin{document}

  \begin{tikzpicture}
    % In this MWE, I'll use "\strokecolor" and "\fillcolor" in this example
    % instead of the commands I'm looking for to retrieve the current stroke
    % and fill colors

    \begin{scope}[draw=black, fill=white]
      \def\strokecolor{black}
      \def\fillcolor{white}

      \node[test] at (0em, 0em) {};
      \node[test, invert] at (12em, 0em) {};
    \end{scope}

    \begin{scope}[draw=blue, fill=red]
      \def\strokecolor{blue}
      \def\fillcolor{red}

      \node[test] at (0em, 12em) {};
      \node[test, invert] at (12em, 12em) {};
    \end{scope}
  \end{tikzpicture}

\end{document}

Here is the intended result:

MWE result

I tried to use the "\color@pgfstrokecolor" and "\color@pgffillcolor". However, I then get the following error:

! Package xcolor Error: Undefined color `\color@pgfstrokecolor'.

How can I retrieve the current stroke and fill colors in a PGF shape declaration ?

Best Answer

I used percusse's trick in the answer at How to save the current color in PGF/TikZ?.

Note also that the OP wrongly reversed the sense of \makeatletter and \makeatother which would never allow a solution, until corrected.

\documentclass[varwidth,border=50]{standalone}
\usepackage{tikz}
\makeatletter
\tikzset{%
  get stroke color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedstrokecolor% Jump we have \global\let\pgf...
    \csname\string\color@pgfstrokecolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
  restore stroke color/.code={\pgf@setstrokecolor#1},
  get fill color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedfillcolor% Jump we have \global\let\pgf...
    \csname\string\color@pgffillcolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
  restore fill color/.code={\pgf@setfillcolor#1},
}

\pgfkeys{%
  /pgf/invert/.initial=no,%
  /pgf/invert/.default=yes,%
}

\pgfdeclareshape{test}{%
  \inheritsavedanchors[from=circle]%
  \inheritanchorborder[from=circle]%
  \inheritanchor[from=circle]{center}%
  %
  \backgroundpath{%
    \pgfpathcircle{\pgfpointorigin}{5em}%
  }%
  %
  \beforebackgroundpath{%
    \def\borderColor{\strokecolor}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
%      \tikzset{restore fill color/.expand once=\pgfsavedfillcolor}
%      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
    \else%
      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
      \tikzset{restore fill color/.expand once=\pgfsavedstrokecolor}
    \fi%
    \pgfsetlinewidth{.5em}%
    \pgfpathcircle{\pgfpointorigin}{5em}%
    \pgfusepath{fill,stroke}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
%      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
    \else%
      \tikzset{restore stroke color/.expand once=\pgfsavedfillcolor}
    \fi%
    \pgfmoveto{\pgfpointpolar{135}{4em}}%
    \pgflineto{\pgfpointpolar{-45}{4em}}%
    \pgfusepath{stroke}%
  }%
}
\makeatother
\begin{document}

  \begin{tikzpicture}
    \begin{scope}[draw=black, fill=white]
      \tikzset{get stroke color}
      \tikzset{get fill color}
      \node[test] at (0em, 0em) {};
      \node[test, invert] at (12em, 0em) {};
    \end{scope}

    \begin{scope}[draw=blue, fill=red]
      \tikzset{get stroke color}
      \tikzset{get fill color}
      \node[test] at (0em, 12em) {};
      \node[test, invert] at (12em, 12em) {};
    \end{scope}
  \end{tikzpicture}
\end{document}

enter image description here