pgfkeys - 是选择 + 值传递给 graphicx

pgfkeys - 是选择 + 值传递给 graphicx

我正在尝试实现一个宏,它是 graphicx\includegraphics命令的包装器(因为我想以键值方式传递裁剪参数)。在执行此操作时,我首先引入了一个键来设置width(选项includegraphics)。后来我需要相同的宏来设置scaleheight选项。

现在我有三个宏,它们的作用基本相同,我想将它们合并为一个。我看到有一个.is choice我尝试使用的键,但我无法额外传递一个值,也无法将键值对传递给 graphicx。但请看我的尝试:

\documentclass{article}

\usepackage{pgfkeys}
\usepackage{graphicx}

% \pgfkeys{
%   /testing/.cd,
%   scaling/.is choice,
%   scaling/width/.code=\def\testing{width=#1},
%   scaling/height/.code=\def\testing{height=#1},
%   scaling/scale/.code=\def\testing{scale=#1},
% }

\pgfkeys{
    /graphicx/.cd,
    left/.initial=0cm, left/.default=0cm,
    % left/.store in=\owngraphicx@left,
    right/.initial=0cm, right/.default=0cm,
    top/.initial=0cm, top/.default=0cm,
    bottom/.initial=0cm, bottom/.default=0cm,
    page/.initial={1}, page/.default={1},
    width/.initial=\linewidth, width/.default=\linewidth,
}
\newcommand{\slidesS}[2][]{%
    \pgfkeys{/graphicx/.cd,left,right,top,bottom,page,#1}%
    \fbox{%
        \includegraphics[%
        page=\pgfkeysvalueof{/graphicx/page},%
        scale=\pgfkeysvalueof{/graphicx/width},%
        clip,%
        trim=\pgfkeysvalueof{/graphicx/left} \pgfkeysvalueof{/graphicx/bottom} \pgfkeysvalueof{/graphicx/right} \pgfkeysvalueof{/graphicx/top},%
        ]{#2}%
    }%
}
\newcommand{\slidesW}[2][]{%
    \pgfkeys{/graphicx/.cd,left,right,top,bottom,page,#1}%
    \fbox{%
        \includegraphics[%
        page=\pgfkeysvalueof{/graphicx/page},%
        width=\pgfkeysvalueof{/graphicx/width},%
        clip,%
        trim=\pgfkeysvalueof{/graphicx/left} \pgfkeysvalueof{/graphicx/bottom} \pgfkeysvalueof{/graphicx/right} \pgfkeysvalueof{/graphicx/top},%
        ]{#2}%
    }%
}
\newcommand{\slidesH}[2][]{%
    \pgfkeys{/graphicx/.cd,left,right,top,bottom,page,#1}%
    \fbox{%
        \includegraphics[%
        page=\pgfkeysvalueof{/graphicx/page},%
        height=\pgfkeysvalueof{/graphicx/width},%
        clip,%
        trim=\pgfkeysvalueof{/graphicx/left} \pgfkeysvalueof{/graphicx/bottom} \pgfkeysvalueof{/graphicx/right} \pgfkeysvalueof{/graphicx/top},%
        ]{#2}%
    }%
}
\newcommand{\inputFile}{image.png}

\begin{document}

% \pgfkeys{
%   /testing/.cd,
%   scaling={height=10cm},
% }

\slidesS[left=1.8982075471698134cm, right=10cm, bottom=1cm, top=5.75cm, width=1]{\inputFile}
% \includegraphics[\testing]{\inputPdfFile}

\end{document}

所注释的内容是我试图捕捉的键+值is choice

关于如何正确执行此操作的任何想法(使用\testingin\includegraphics不起作用,因为width=10cm它被视为一个选项,而不是 key=value 我认为)

答案1

此答案与使用 的答案类似expkv-cs,但这次使用pgfkeys。想法保持不变:仅定义四个键leftbottomrighttop,并将所有未知键转发给\includegraphics。对于 ,转发部分稍微复杂一些pgfkeys。如果 和 不是必需的,此答案不包含省略cliptrim(如果您想要这个,我也可以将其内置pgfkeys,只需发表评论即可)。

\documentclass{article}

\usepackage{graphicx}
\usepackage{pgfkeys}

\makeatletter
\pgfqkeys{/graphicx}
  {
    .is family
    ,left/.initial=0pt, left/.default=0pt
    ,bottom/.initial=0pt, bottom/.default=0pt
    ,right/.initial=0pt, right/.default=0pt
    ,top/.initial=0pt, top/.default=0pt
    ,.unknown/.code=%
      \edef\graphicwrap@unknown
        {%
          \unexpanded\expandafter{\graphicwrap@unknown},%
          \pgfkeyscurrentname
          \ifx\pgfkeysnovalue#1\else={\unexpanded{#1}}\fi
        }%
  }
\newcommand*\graphicwrap@unknown{}
\newcommand\graphicwrap[2][]
  {%
    \begingroup
      \pgfqkeys{/graphicx}{#1}%
      \expandafter\graphicwrap@\expandafter{\graphicwrap@unknown}{#2}%
    \endgroup
  }
\newcommand\graphicwrap@[2]
  {%
    \includegraphics
      [%
         clip
        ,trim=\pgfkeysvalueof{/graphicx/left}
              \pgfkeysvalueof{/graphicx/bottom}
              \pgfkeysvalueof{/graphicx/right}
              \pgfkeysvalueof{/graphicx/top}
        ,#1%
      ]%
      {#2}%
  }
\makeatother

\begin{document}
\graphicwrap[width=5cm, left=2cm]{example-image-duck}
\graphicwrap[scale=0.5, left=2cm]{example-image-duck}

% of course old names still work as well
\graphicwrap[clip, trim=2cm 0 0 0]{example-image-duck}
\end{document}

在此处输入图片描述


clip仅在trim使用其中一个密钥时才使用 (没有第二层密钥,而是让密钥不仅仅是存储其值) 的版本:

\documentclass{article}

\usepackage{graphicx}
\usepackage{pgfkeys}

\makeatletter
\pgfqkeys{/graphicx}
  {
    .is family
    ,left/.initial=0pt, left/.default=0pt
    ,bottom/.initial=0pt, bottom/.default=0pt
    ,right/.initial=0pt, right/.default=0pt
    ,top/.initial=0pt, top/.default=0pt
    ,left/.code=\pgfkeyssetvalue{/graphicx/left}{#1}\let\graphicwrap@do\graphicwrap@clip
    ,bottom/.code=\pgfkeyssetvalue{/graphicx/bottom}{#1}\let\graphicwrap@do\graphicwrap@clip
    ,right/.code=\pgfkeyssetvalue{/graphicx/right}{#1}\let\graphicwrap@do\graphicwrap@clip
    ,top/.code=\pgfkeyssetvalue{/graphicx/top}{#1}\let\graphicwrap@do\graphicwrap@clip
    ,.unknown/.code=%
      \edef\graphicwrap@unknown
        {%
          \unexpanded\expandafter{\graphicwrap@unknown},%
          \pgfkeyscurrentname
          \ifx\pgfkeysnovalue#1\else={\unexpanded{#1}}\fi
        }%
  }
\newcommand\graphicwrap@clip[1]
  {%
    \includegraphics
      [%
         clip
        ,trim=\pgfkeysvalueof{/graphicx/left}
              \pgfkeysvalueof{/graphicx/bottom}
              \pgfkeysvalueof{/graphicx/right}
              \pgfkeysvalueof{/graphicx/top}
        ,#1%
      ]%
  }
\newcommand\graphicwrap@noclip[1]{\includegraphics[#1]}
\let\graphicwrap@do\graphicwrap@noclip
\newcommand*\graphicwrap@unknown{}
\newcommand\graphicwrap[2][]
  {%
    \begingroup
      \pgfqkeys{/graphicx}{#1}%
      \expandafter\graphicwrap@do\expandafter{\graphicwrap@unknown}{#2}%
    \endgroup
  }
\makeatother

\begin{document}
\graphicwrap[width=5cm, left=2cm]{example-image-duck}
\graphicwrap[scale=0.5, left=2cm]{example-image-duck}

% of course old names still work as well
\graphicwrap[clip, trim=2cm 0 0 0]{example-image-duck}
\end{document}

答案2

下面使用expkv-cs,因为在我看来,设置一个只使用少数几个键的小宏要容易得多(好吧,我是包的作者,所以可能不那么谦虚,而且相当有偏见)。在这里,通过省略检查 和 是否clip完全trim必要,可以更简单。

expkv-cs支持特殊...密钥,这意味着所有未知密钥都收集在那里。这样可以轻松地将未知密钥转发到graphicx。这种方法的缺点:如果使用leftbottomrighttop中的任何一个密钥,它们将放在 的 key=value 列表中的首位\includegraphics,因此密钥的顺序并不相同(这应该不是什么大问题)。

\documentclass{article}

\usepackage{graphicx}

\usepackage{expkv-cs} % <- sorry, not pgfkeys here
\makeatletter
% optional argument grabbing, expkv-cs uses mandatory arguments
\newcommand\graphicwrap[1][]{\graphicwrap@{#1}}
% internal keys and their initial values here
\ekvcSplitAndForward\graphicwrap@\graphicwrap@do
  {
     internal-left   = 0pt      % #1
    ,internal-bottom = 0pt      % #2
    ,internal-right  = 0pt      % #3
    ,internal-top    = 0pt      % #4
    ,internal-any    = \@gobble % #5: used as a flag that clip is needed
    ,...                        % #6: unknown keys
  }
% additional keys (the front-facing ones) and what they do
\ekvcSecondaryKeys\graphicwrap@
  {
     meta left   = {internal-any=\@firstofone, internal-left   = {#1}}
    ,meta bottom = {internal-any=\@firstofone, internal-bottom = {#1}}
    ,meta right  = {internal-any=\@firstofone, internal-right  = {#1}}
    ,meta top    = {internal-any=\@firstofone, internal-top    = {#1}}
  }
% output macro
\newcommand\graphicwrap@do[7]
  {\expandafter\includegraphics\expandafter[#5{clip, trim=#1 #2 #3 #4}, #6]{#7}}
\makeatother

\begin{document}
\graphicwrap[width=5cm, left=2cm]{example-image-duck}
\graphicwrap[scale=0.5, left=2cm]{example-image-duck}

% of course old names still work as well
\graphicwrap[clip, trim=2cm 0 0 0]{example-image-duck}
\end{document}

在此处输入图片描述


为了进行比较,以下是无需检查是否需要clip和的变体:trim

\documentclass{article}

\usepackage{graphicx}

\usepackage{expkv-cs} % <- sorry, not pgfkeys here
\makeatletter
% optional argument grabbing, expkv-cs uses mandatory arguments
\newcommand\graphicwrap[1][]{\graphicwrap@{#1}}
% keys and their initial values here
\ekvcSplitAndForward\graphicwrap@\graphicwrap@do
  {
     left   = 0pt      % #1
    ,bottom = 0pt      % #2
    ,right  = 0pt      % #3
    ,top    = 0pt      % #4
    ,...               % #5: unknown keys
  }
% output macro
\newcommand\graphicwrap@do[6]{\includegraphics[clip, trim=#1 #2 #3 #4, #5]{#6}}
\makeatother

\begin{document}
\graphicwrap[width=5cm, left=2cm]{example-image-duck}
\graphicwrap[scale=0.5, left=2cm]{example-image-duck}

% of course old names still work as well
\graphicwrap[clip, trim=2cm 0 0 0]{example-image-duck}
\end{document}

相关内容