我发现如果将二维码放在 latex 中的命令内,则 \qrcode 的输出会失真。下面有一个 MWE,显示了 2 个实际上相同的二维码,一个是在名为 \contact 的 \newcommand 内生成的,另一个是在没有它的情况下生成的。我使用的是 qrcode 包。
差异很明显,实际上,当我扫描两个代码时,左侧的一个被识别为联系人,而另一个则不是。这是 MWE:
\documentclass[border=1cm]{standalone}
\usepackage[]{qrcode}
\newcommand{\contact}{
\qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}
}
\begin{document}
\qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}
\contact
\end{document}
差异实际上是显而易见的。右边的是扭曲的:
我已经在 Debian Buster 下测试了这种行为,使用 Xelatex 和 Pdflatex。两者都表现出相同的行为。问题是,在这种情况下,有没有办法解决这种扭曲?究竟是什么导致了这种情况?
此致,
Ch。
答案1
引用qrcode
文档:
但是,与所有逐字模式一样,由于 TEX 在第一次遇到字符时会不可撤销地设置 catcode,因此如果宏
\qrcode
包含在另一个宏中,则此模式将不起作用。例如,如果你\qrcode
在 或 中\fbox
调用\marginpar
,并且你的 URL 包含其中一个特殊字符,则你将遇到错误消息或(更糟的是,因为肉眼无法检测到)错误的 QR 码排版。在这种情况下,你仍然可以通过#$&^_~% \{}
使用额外的反斜杠转义来包含任何字符;只要它们最终未扩展地传递给\qrcode
,它们就会产生正确的 QR 码。可以使用 获得换行符\?
。
所以这是由换行符和空格(缩进)引起的。你可以通过将换行符替换为 来修复它\?
。
具有相同条形码的示例:
\documentclass[border=1cm]{standalone}
\usepackage[]{qrcode}
\newcommand{\contact}{
\qrcode[]{\?%
BEGIN:VCARD\?%
VERSION:4.0\?%
EMAIL:[email protected]\?%
FN:John Doe\?%
N:Doe;John;;;\?%
TEL;TYPE=home:123456789\?%
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d\?%
URL:www.doe.net\?%
END:VCARD\?%
}
}
\begin{document}
\qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}
\contact
\end{document}
答案2
问题是:
\qrcode
首先修改 catcode-régime,然后调用一些内部宏。
内部宏反过来会导致 LaTeX 从 .tex 输入文件读取并根据修改后的 catcode-régime 标记其参数。
\qrcode
在定义宏时,在正常/未修改的 catcode-régime 下对整个调用进行标记时,修改后的 catcode-régime 下的读取和标记参数会被超越\contact
。
从 .tex 输入文件读取并在不同的 catcode-régimes 下对事物进行标记会产生不同的标记集,进而产生不同的二维码。
定义宏的一种解决方法是读取和标记对verbatim-catcode-régime 下的\contact
整个调用,然后将其传递给,后者又假装将未扩展的事物写入文本文件并读取该文本文件。'阅读部分确保事物得到重新标记,从而影响事物所执行的 catcode-régime 的更改。\qrcode
\scantokens
\scantokens
\qrcode
我的 -eh- 私人 LaTeX 编程工具包包含一个宏\UDcollectverbarg
,可用于在 verbatim-catcode-régime 下对事物进行标记,然后将它们作为参数传递给其他命令:
\documentclass[border=1cm]{standalone}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Implement stuff for reading arguments "verbatim":
%
% Usually \endlinechar has the value `\^^M which implies that
% LaTeX usually does insert character 13 (return) at each line-ending.
% There are situations where this needs to be replaced by the
% newline-character (usually ^^J). (E.g., with \scantokens'
% unexpanded-writing-to-file-part...)
%
% Maybe the routine for \UDcollectverbarg could be shorter but I wanted
% both syntax |verbatim-arg| and syntax {verbatim-arg} to be possible.
%
% Syntax of \UDcollectverbarg:
%
% \UDcollectverbarg{<^^M-replacement>}{<Mandatory 1>}{<Mandatory 2>}<verbatim-Arg>
%
% yields:
%
% <Mandatory 1>{<Mandatory2>{<verbatim-Arg>}}
%
% Syntax of \UDconcatverbarg:
%
% \UDconcatverbarg{<^^M-replacement>}{<Mandatory 1>}{<Mandatory 2>}<verbatim-Arg>
%
% yields:
%
% <Mandatory 1>{<Mandatory2><verbatim-Arg>}
%
% with each character ^^M (usually=\endline-char) replaced by
% token-sequence <^^M-replacement>
%
% The Mandatory-Arguments are mandatory. If they consist of several
% tokens, they must be nested into catcode-1/2-character-pair / braces.
% If reading is necessary, they will be read under normal catcode-
% conditions.
% The verbatim-Arg is also mandatory. It will be read under
% verbatim-catcode-conditions. If its first character is a brace,
% it will be "assumed" that the argument is nested into braces.
% Otherwise it will be assumed, that the argument is delimited
% by the first character - like the argument of \verb.
%
% Empty-lines will not be ignored.
%
% By nesting calls to \UDcollectverbarg within \UDcollectverbarg's first
% argument, you can collect "verbatim-arguments" within its second
% argument.
%
% E.g.,
%
% \UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}}% <- Mandatory 1
% {<actionB>}% <- Mandatory
% <verbatim-Arg1><verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
% \UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}% <- Mandatory 1
% {<actionB><verbatim-Arg1>}% <- Mandatory 2
% <verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
% \UDcollectverbarg{<^^M-replacement>}{<actionA>}% <- Mandatory 1
% {<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}}% <- Mandatory 2
% <verbatim-Arg3>
%
% yields:
%
% <actionA>{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
% Assume <actionA> = \@firstofone -> equals:
%
% \@firstofone{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
% yields:
%
% <actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}
\newcommand\@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
\@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
\begingroup
\catcode`\^^M=12 %
\@firstoftwo{%
\endgroup%%%%
\newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
\newcommand*\@UDEndlreplace{}%
\long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
\@CheckWhetherNull{#3}%
{ #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
}%
}{}%
\newcommand\UDcollectverbarg{\@UDverbarg{\@UDcollectverbarg}}%
\newcommand\@UDverbarg[4]{%
\@bsphack
\begingroup
\let\do\@makeother\dospecials
\catcode`\{=1 %
\catcode`\ =10 %
\@ifnextchar\bgroup
{\catcode`\}=2 \@@UDverbarg{#1}{#2}{#3}{#4}{}}%
{\do\{\@@UDverbarg{#1}{#2}{#3}{#4}}%
}%
\newcommand\@@UDverbarg[5]{%
\do\ %
\catcode`\^^M=12 %
\long\def\@tempb##1#5{%
\edef\@tempb{##1}%
\@onelevel@sanitize\@tempb
\expandafter\UDEndlreplace\expandafter{\@tempb}{#2}{\def\@tempb}%
\expandafter#1\expandafter{\@tempb}{#3}{#4}%
}%
\@tempb
}%
\newcommand\@UDcollectverbarg[3]{%
\endgroup
\@esphack
#2{#3{#1}}%
}%
\makeatother
% Implementing stuff for reading arguments "verbatim" done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage[]{qrcode}
\begingroup
\newlinechar=`\^^J %
\catcode`\^^J=12 %
\UDcollectverbarg{^^J}{\endgroup\newcommand{\contact}}{\scantokens}|%
\qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}%
|%
\begin{document}
\qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}
\contact
\end{document}