如何正确扩展宏\myviewport
以便将其解析为viewport=0pt 10pt 100pt 200pt
参数\includegraphics[clip, \myviewport]{somepdf.pdf}
?
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\newcommand*{\aport}{45.29pt 86.28pt 235pt 187pt}
\includegraphics[clip, viewport={\aport}]{somepdf.pdf}
\end{document}
错误:! Argument of \Gread@parse@vp has an extra }.
我的简单想法是基于
如果宏
起作用的是为每个视口值提供单独的宏:
\documentclass{article}
\usepackage{graphicx}
\usepackage{calc}
\begin{document}
\newlength{\Xoffset}
\setlength{\Xoffset}{35pt}
\newlength{\myl}
\setlength{\myl}{235pt - \Xoffset}
\newcommand*{\lux}{200pt}
\includegraphics[clip, viewport=10pt 50pt \lux{} \the\myl{}, page=3]{somepdf.pdf}
\end{document}
请注意,\myl
是一个长度并且\lux
是一个“字符串”。
从长远来看,我想自动裁剪一些 pdf 文件(其媒体框不是从 0 0 开始的):
\documentclass{article}
\usepackage{graphicx}
\usepackage{calc}
\newlength{\Xoffset}
\newlength{\Yoffset}
\newcommand*{\setpdfoffset}[2]{
\setlength{\Xoffset}{#1}
\setlength{\Yoffset}{#2}
}
\newcommand*{\aviewport}{} %set an empty default
\setpdfoffset{0pt}{0pt} %set a default
\newcommand*{\setviewport}[4]{
\newlength{\mylux}\setlength{\mylux}{#1-\Xoffset}
\newlength{\myluy}\setlength{\myluy}{#2-\Yoffset}
\newlength{\myrox}\setlength{\myrox}{#3-\Xoffset}
\newlength{\myroy}\setlength{\myroy}{#4-\Yoffset}
\renewcommand*{\aviewport}{viewport={\the\mylux} {\the\myluy} {\the\myrox} {\the\myroy}}
}
\begin{document}
%in Windows command line:
% pdfinfo -box somepdf.pdf |awk "/MediaBox/ {print; print \"Xoffset=\"$2 \" Yoffset=\"$3\"\n\"; print \"\\newlength{\\Xoffset}\\setlength{\\Xoffset}{\"$2\"pt} \\newlength{\\Yoffset}\\setlength{\\Yoffset}{\"$3\"pt}\"}"
\setpdfoffset{35.29pt}{36.28pt}
\setviewport{45.29pt}{86.28pt}{235pt}{187pt}
\emph{\aviewport}
\fbox{\includegraphics[clip, \aviewport{}, page=2]{somepdf}
\end{document}
错误:keyval: viewport={10.0pt} {50.0pt} {199.71pt} {150.72pt} undefined. ...lip, \aviewport]{somepdf}}
XeLaTeX 是我的首选,但 pdfLaTeX 也不喜欢这个代码。
\setpdfoffset
奖励:使用获取 X 和 Y 偏移值\input{|"pdfinfo -box somepdf.pdf |awk ..."}
,但这是一个逃避问题而不是扩展问题。
答案1
以下是几种方法:
\documentclass{article}
\usepackage{graphicx}
\newcommand{\myviewport}{viewport=0pt 10pt 200pt 50pt}
\begin{document}
\includegraphics[clip, viewport=0pt 10pt 200pt 50pt]{example-image}
\begingroup\edef\x{\endgroup\noexpand\includegraphics[clip, \myviewport]{example-image}}\x
{\let\includegraphics\relax\xdef\x{\includegraphics[clip, \myviewport]{example-image}}}\x
\end{document}
第一个显示预期的输出应该是什么样的。
第二个定义了 的扩展版本\x
,其中\includegraphics[..]{...}
是\includegraphics
未扩展的。它也是本地的,因为\x
使用后会被丢弃。它非常类似于
\edef\x{\noexpand\includegraphics[clip, \myviewport]{example-image}}\x
无需本地化\x
。
第三个定义了一个类似的\x
,现在是全局的(也扩展了,因此\xdef
)。但是,为了避免扩展,\includegraphics
它被设置为\relax
组内的。这可以防止它通过调用扩展\xdef
,并且它也存在于组中。特别是\show\x
揭示了
> \x=macro:
->\includegraphics [clip, viewport=0pt 10pt 200pt 50pt]{example-image}.
viewport
,和trim
bb
(b
圆角b
牛)键很特殊,因为要求特定值输入。输入有为展开形式#1 #2 #3 #4
,并使用 TeX 的参数文本或 进行识别\def
。因此,如果匹配不准确,则可能会将错误的参数分配给错误的元素,从而导致您遇到的问题。
在一定程度上,其他宏也可以以宏形式使用。至少,您必须使用显式的=
:
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics[width=100pt]{example-image}
\newcommand{\mywidth}{width}%
\newcommand{\widthdimen}{100pt}%
\includegraphics[\mywidth=\widthdimen]{example-image}
%\newcommand{\mywidthkeyval}{width=100pt}%
%\includegraphics[\mywidthkeyval]{example-image}% Does not work
\includegraphics[clip, viewport=10pt 10pt 50pt 50pt]{example-image}
\newcommand{\myviewport}{viewport}%
\newcommand{\viewportvals}{10pt 10pt 50pt 50pt}%
\includegraphics[clip, \myviewport=10pt 10pt 50pt 50pt]{example-image}
%\includegraphics[clip, \myviewport=\viewportvals]{example-image}% Does not work
\end{document}
答案2
viewport
选项或的四个值trim
由分隔空格标识。包中为这些选项定义的解析器graphicx
需要显式空格,如果空格隐藏在宏中,解析器将失败。
下面的示例重新定义选项(以与重新定义viewport
选项相同的方式)以扩展其参数,然后将扩展的值传递给原始选项代码:trim
\documentclass{article}
\usepackage{graphicx}
\makeatletter
% Remember original option `viewport` as `viewport@org`
\let\KV@Gin@viewport@org\KV@Gin@viewport
% Redefine option `viewport` to expand the argument and
% pass it to option `viewport@org`.
\define@key{Gin}{viewport}{%
\begingroup
\edef\x{\endgroup
\noexpand\setkeys{Gin}{viewport@org={#1}}%
}\x
}
\makeatother
\begin{document}
\newcommand*{\aport}{45.29pt 86.28pt 235pt 187pt}
\includegraphics[clip, viewport=\aport]{tiger}
\end{document}
等号和逗号是 LaTeX 键值列表(包keyval
和朋友)中的语法字符。如果这些字符隐藏在宏中,键值解析器将失败。但可以定义一个新选项,带有graphicx
一个参数,该参数将作为键值列表展开并再次执行:
\documentclass{article}
\usepackage{graphicx}
\makeatletter
\define@key{Gin}{expandoptions}{%
\begingroup
\edef\x{\endgroup
\noexpand\setkeys{Gin}{#1}%
}\x
}
\makeatother
\begin{document}
\newcommand*{\viewaport}{viewport=45.29pt 86.28pt 235pt 187pt, clip}
\includegraphics[expandoptions=\viewaport]{tiger}
\end{document}
答案3
您可以为 定义一个新键\includegraphics
,我将其命名为xviewport
。
\documentclass{article}
\usepackage{graphicx}
\usepackage{calc}
\makeatletter
\define@key{Gin}{xviewport}[]{%
\begingroup\edef\x{%
\endgroup\noexpand\setkeys{Gin}{viewport=\x@viewport}%
}\x
}
\newlength{\Xoffset}
\newlength{\Yoffset}
\newcommand*{\setpdfoffset}[2]{%
\setlength{\Xoffset}{#1}%
\setlength{\Yoffset}{#2}%
}
\newcommand*{\setviewport}[4]{%
\def\x@viewport{%
{\the\dimexpr#1-\Xoffset}
{\the\dimexpr#2-\Yoffset}
{\the\dimexpr#3-\Xoffset}
{\the\dimexpr#4-\Yoffset}%
}%
}
\makeatother
\begin{document}
\setpdfoffset{35.29pt}{36.28pt}
\setviewport{45.29pt}{86.28pt}{235pt}{187pt}
\fbox{\includegraphics[clip, xviewport]{example-image.pdf}}
\end{document}
答案4
这是可行的,但可能不够通用,无法满足您的需要:
\documentclass{article}
\usepackage[demo]{graphicx}
\begin{document}
\newcommand*{\aport}{45.29pt 86.28pt 235pt 187pt}
\def\X{\includegraphics[clip, viewport=}
\expandafter\X\aport]{somepdf.pdf}
\end{document}