\newcommand 扭曲 \qrcode

\newcommand 扭曲 \qrcode

我发现如果将二维码放在 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}

差异实际上是显而易见的。右边的是扭曲的:

QR 码:左侧为未使用 newcommand 生成的二维码。右侧为未使用 newcommand 生成的二维码

我已经在 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首先修改 c​​atcode-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}

在此处输入图片描述

相关内容