2

I've been reading a lot of posts lately on the difference between using the key-value interface and the handler interface of pgfkeys. To my understanding, the same values can be stored and retrieved in both ways. For example:

\documentclass{article}
\usepackage{tikz}
\pgfkeys{
    /testa/.initial,
    /testb/.store in=\testbvalue,
}
\begin{document}
    \def\foo{bar}
    \pgfkeys{/testa=\foo,/testb=\foo}
    \pgfkeysvalueof{/testa}

    \testbvalue

    \pgfkeysgetvalue{/testa}\testavalue     
    \meaning\testavalue

    \meaning\testbvalue

\end{document}

Here the same value can be retrieved through \pgfkeysvalueof{/testa} and \testbvalue. In fact the meaning of \testavalue and \testbvalue is the same (which is no surprise). But then, why does the following code work

\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{overpic}

\pgfkeys{
    /icon/.cd,
    width/.initial,
    overlay/.store in=\iconoverlay,
    set defaults/.unknown/.code={\pgfkeys{/icon/\pgfkeyscurrentname/.default=#1}}
}
\newcommand\icondefaults[1]{%
    \pgfkeys{/icon/set defaults/.cd, #1}%
}
\newcommand\ifkeyempty[3]{%
    \pgfkeysgetvalue{#1}{\keyvalue}%
    \ifempty{\keyvalue}{#2}{#3}%
}
\newcommand\ifempty[3]{%
    \def\novalue{\pgfkeysnovalue}%
    \def\empty{}%
    \ifboolexpr{test {\ifdefequal{#1}{\empty}} or test {\ifdefequal{#1}{\novalue}}}{#2}{#3}%
}
\newcommand{\icon}[2][]{%
    {%
        \pgfkeys{/icon/.cd,width,overlay,#1}% Reset to default values
        \def\options{}%
        \ifkeyempty{/icon/width}{}{\edef\options{width=\pgfkeysvalueof{/icon/width},\options}}%
        \ifempty{\iconoverlay}{%
            \edef\graphic{\noexpand\includegraphics[\options]{#2}}%
        }{%
            \edef\overlay{\noexpand\begin{overpic}[\options]{#2}}%
            \def\graphic{\overlay\put(0,0){\iconoverlay}\end{overpic}}%
        }%
        \graphic%
    }%
}%

\begin{document}

\icondefaults{width=6cm}
\icon{example-image} % Image gets default width 6cm
\icon[width=2cm,overlay={\icon{example-image-overlay}}]{example-image} % Image gets width 2cm, while the overlaid image gets default width 6cm
\icon{example-image} % Image gets default width 6cm

\end{document}

While next section of code does not work. The only difference is that /.store in is not used for the key overlay, and hence \pgfkeysvalueof is used to access the value of the key. It results in an error TeX capacity exceeded.

\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{overpic}

\pgfkeys{
    /icon/.cd,
    width/.initial,
    overlay/.initial,
    set defaults/.unknown/.code={\pgfkeys{/icon/\pgfkeyscurrentname/.default=#1}}
}
\newcommand\icondefaults[1]{%
    \pgfkeys{/icon/set defaults/.cd, #1}%
}
\newcommand\ifkeyempty[3]{%
    \pgfkeysgetvalue{#1}{\keyvalue}%
    \ifempty{\keyvalue}{#2}{#3}%
}
\newcommand\ifempty[3]{%
    \def\novalue{\pgfkeysnovalue}%
    \def\empty{}%
    \ifboolexpr{test {\ifdefequal{#1}{\empty}} or test {\ifdefequal{#1}{\novalue}}}{#2}{#3}%
}
\newcommand{\icon}[2][]{%
    {%
        \pgfkeys{/icon/.cd,width,overlay,#1}% Reset to default values
        \def\options{}%
        \ifkeyempty{/icon/width}{}{\edef\options{width=\pgfkeysvalueof{/icon/width},\options}}%
        \ifkeyempty{/icon/overlay}{%
            \edef\graphic{\noexpand\includegraphics[\options]{#2}}%
        }{%
            \edef\overlay{\noexpand\begin{overpic}[\options]{#2}}%
            \def\graphic{\overlay\put(0,0){\pgfkeysvalueof{/icon/overlay}}\end{overpic}}%
        }%
        \graphic%
    }%
}%

\begin{document}

\icondefaults{width=6cm}
\icon{example-image} % Image gets default width 6cm
\icon[width=2cm,overlay={\icon{example-image-overlay}}]{example-image} % Image gets width 2cm, while the overlaid image gets default width 6cm
\icon{example-image} % Image gets default width 6cm

\end{document}

Can anyone explain this behavior? Is my understanding wrong, that the same value is stored and retrieved in both cases, just in different ways?

1

They are not equivalent. /.store in handler simply performs a \def operation and does not hold the value. However setting a key allows one to retrieve a value that is set in that scope. That's why in the second case the key has to be set.

That's why the first one works because the setting to default behavior is available locally to both levels of recursion. However the second one doesn't change the value of the key.

For that you have to explicitly set the overlay key to nothing at the line

\pgfkeys{/icon/.cd,width,overlay=,#1}% Notice the equal sign for the overlay key

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.