% \iffalse meta-comment % % qrcode.ins % Copyright 2014 by Anders O.F. Hendrickson (anders.hendrickson@snc.edu) % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Anders O.F. Hendrickson. % % This work consists of the files qrcode.dtx and qrcode.ins % and the derived file qrcode.sty. % % \fi % % \iffalse %<*driver> \ProvidesFile{qrcode.dtx} % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{qrcode} %<*package> [2015/01/08 v1.51 QR code generation] % % %<*driver> \documentclass{ltxdoc} \usepackage{hyperref} \usepackage[nolinks]{qrcode} \EnableCrossrefs \CodelineIndex \OnlyDescription \RecordChanges \begin{document} \DocInput{qrcode.dtx} \PrintChanges %\PrintIndex \end{document} % % \fi % % \CheckSum{0} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.0}{2014/09/26}{Initial version} % \changes{v1.5}{2015/01/08}{Added support for new lines and hyperlinks.} % \changes{v1.51}{2015/01/14}{Bug fix.} % % \GetFileInfo{qrcode.sty} % % \DoNotIndex{\newcommand,\newenvironment,\def} % % \def\F{F} % % \title{The \textsf{qrcode} package: \\ % \makebox[0pt][r]{\raisebox{-0.3\height}[0pt][0pt]{\qrcode[hyperlink,tight]{http://ctan.org/pkg/qrcode}}\rule{0.75in}{0pt}}Quick Response code \\ % generation in \LaTeX\thanks{This document % corresponds to \textsf{qrcode}~\fileversion, dated \filedate.}} % \author{Anders Hendrickson\\ St.~Norbert College, De~Pere, WI, USA \\ \texttt{anders.hendrickson@snc.edu}} % \date{January 8, 2015} % % \maketitle % % % \section{Introduction} % % The proliferation of smartphones and tablets has led to the widespread % use of Quick Response (QR) codes, which encode numeric, alphanumeric, kanji, % or binary information into a square matrix of black and white pixels called modules. % Although QR codes can encode any information up to almost three kilobytes, % their most common use is as physical hyperlinks: a mobile device scans % a printed QR code, decodes a URL, and automatically points a browser to that location. % % It is natural to want to include QR codes in certain \LaTeX\ documents; % for example, one may want to direct the reader of a printed page to % related interactive content online. % Before now, the only \LaTeX\ package for producing QR codes was the % immensely flexible {\tt pst-barcode}. As that package relies on % {\tt pstricks}, however, it can be difficult to integrate with % a pdf\LaTeX\ workflow,\footnote{% % The {\tt auto-pst-pdf} or {\tt pstool} packages can make this possible % by automatically running % \LaTeX${}\rightarrow \tt dvips \rightarrow ps2pdf \rightarrow pdfcrop$ % for each barcode generated in {\tt pstricks}, % so long as the user is able and willing to enable {\tt\string\write18} % in {\tt pdflatex} and install Perl. % Judging by questions on {\tt tex.stackexchange.com} and {\tt latexcommunity.org}, % this is a significant hurdle for some users. % Moreover, according to {\tt http://tex.stackexchange.com/questions/72876/} % this workflow may have trouble if the QR code is in a header.} % and a pdf\LaTeX\ user may not want the extra overhead just to produce a QR code. % If one wants to avoid {\tt pstricks}, a Lua\TeX\ solution was proposed at % {\tt http://tex.stackexchange.com/questions/89649/}, % and a plain\TeX\ solution can be found at % {\catcode`\~=12\tt http://ktiml.mff.cuni.cz/~maj/QRcode.TeX}, % but until now no \LaTeX\ package had been available that did not call on outside machinery. % % The {\tt qrcode} package, in contrast, implements the QR code algorithm using % only \TeX\ and \LaTeX\ commands, so it should work with any \LaTeX\ workflow. % Because it draws the squares constituting a QR code using the \TeX\ primitive % |\rule|, there is no need to load any graphics package whatsoever. % For a user who merely wants a QR code, this is the simplest solution. % % \section{Usage}\label{sect:usage} % % % \DescribeMacro{\qrcode} % The package provides just one command, |\qrcode|, with the following syntax: % \begin{center} % |\qrcode|\oarg{options}\marg{text to be encoded} % \end{center} % For example, |\qrcode[hyperlink,height=0.5in]{http://www.ctan.org}| produces % \begin{center} % \qrcode[hyperlink,height=0.5in]{http://www.ctan.org} % \end{center} % Although the most common use of QR codes is as URLs, % the \meta{text to be encoded} can be almost any typed text. % The few exceptions to this are described in section \ref{sect:specialcharacters}. % % \subsection{Package Options} % % \DescribeMacro{nolinks} % When the |hyperref| package is loaded, % by default |\qrcode| assumes its argument is a URL % and makes the QR code produced a hyperlink to that URL. % This default behavior may be changed by invoking the |nolinks| package option. % For example, most of the QR codes in this document are not in fact URLs, % so this documentation was typeset with |\usepackage[nolinks]{qrcode}|. % The |hyperlinks| option is an antonym to |nolinks| and is the default. % These options have no effect if hyperref is not loaded. % % \DescribeMacro{draft} % \DescribeMacro{final} % Creating QR codes for short URLs takes relatively little time.\footnote{On % this author's laptop, even a 60-character URL (version 4, level M) adds % only about 0.7 seconds of compilation time.} % Because \TeX\ was designed for typesetting, not for extensive computations, % however, if many small QR codes or a single large one are required, % the time spent can be quite noticeable. To save compilation % time while working on a large document, calling the |draft| option % causes the package not to compute QR codes, but merely to insert placeholder % symbols with no data. The |final| option is an antonym to |draft| % and is the default. % \begin{quote} % \begin{tabular}{p{1.25in}p{3.5in}} % {\qrcode[draft,version=15]{http://www.tug.org}} % & % \begin{minipage}{3in} % \tt % |\documentclass{article}| \\ % |\usepackage[draft]{qrcode}| \\ % |\begin{document}| \\ % | \qrcode[version=15]{Dummy code}| \\ % |\end{document}| % \end{minipage} % \end{tabular} % \end{quote} % The placeholder symbol produced in {\tt draft} mode will have the same size % and dimensions as the actual QR code. % % To conserve processing time, when |\qrcode| computes the binary matrix representing % a QR code, it saves that binary data as a string of 1's and 0's % both in a macro and in the {\tt .aux} file. % Thus if the same QR code is desired later in the document, or upon the next % run of \LaTeX, the QR symbol can be redrawn immediately from the saved binary data. % % \DescribeMacro{forget} % There may be times when this is not desired; testing of this package is the chief % example, but one might also have reason to believe that the {\tt .aux} file % contains bad data. % Invoking the |forget| package option causes |\qrcode| to calculate % every QR code anew, even if a QR code for that \meta{text to be encoded}, level, % and version % was read from the {\tt .aux} file or was already computed earlier in the document. % % \subsection{Options} % \DescribeMacro{\qrset} % Several options affect the appearance and encoding of the QR code; % {\tt qrcode} uses the {\tt xkeyval} package to handle the setting % and processing of key-value pairs. % The following options may either be given as optional arguments % to |\qrcode| or changed within a \TeX-grouping using the % macro |\qrset|. % \begin{quote} % \begin{tabular}{p{6cm}p{2in}} % \qrcode{ABCD} % {\qrset{height=1cm}% % \qrcode{EFGH}} % \qrcode{IJKL} % & % \begin{minipage}{3in} % |\qrcode{ABCD}| \\ % |{\qrset{height=1cm}%| \\ % | \qrcode{EFGH}}| \\ % |\qrcode{IJKL}| % \end{minipage} % \end{tabular} % \end{quote} % % \DescribeMacro{height} % The |height=|\meta{dimen} key sets the printed height (and width) of the % QR code. The default value is {\tt 2cm}. % \begin{quote} % \begin{tabular}{p{2in}p{2in}} % \qrcode{ABCD} \qrcode[height=1cm]{ABCD} % & |\qrcode{ABCD}| |\qrcode[height=1cm]{ABCD}| % \end{tabular} % \end{quote} % % \DescribeMacro{level} % The QR code specification (ISO 18004:2006) includes four % levels of encoding: Low, Medium, Quality, and High, in % increasing order of error-correction capabaility. % In general, for a given text a higher error-correction % level requires more bits of information in the QR code. % The key |level=|\meta{level specification} % selects the minimum acceptable level. % The \meta{level specification} may be |L|, |M|, |Q|, or |H|; % the default is |M|. % It may happen that the smallest QR code able to encode % the specified text at the desired level % is in fact large enough to provide a higher level of % error-correction. If so, {\tt qrcode} automatically upgrades to the higher % error-correction level, and a message is printed in the log file. % % \DescribeMacro{version} % QR codes range in size from $21\times 21$ modules (``version 1'') % to $177\times 177$ modules (``version 40''), in steps of 4 modules. % The package automatically selects the smallest version large enough to encode % the specified text at the desired error-correction level. % Nevertheless, there might be occasions when a specific version is required; % for example, perhaps a set of QR codes should have the same dimensions for % aesthetic reasons, even though some encode shorter texts than others. % For this reason, the key |version=|\meta{version specification} allows the user % to specify a minimum version number, from 1 through 40, for the QR code. % Setting |version=0| means ``as small as possible''; this is the default. % If the desired version is not large enough to encode the text, the version % will automatically be increased to accommodate the text, and a message will % be placed in the log file. % \begin{quote} % \begin{tabular}{p{5.2cm}p{3in}} % \raggedright % \qrcode{ABCD} % \qrcode[version=5]{ABCD} % \medskip \\ % \qrcode[version=10]{ABCD} % \qrcode[version=20]{ABCD} % & % \begin{minipage}{3in} % |\qrcode{ABCD}| \\ % |\qrcode[version=5]{ABCD}| \\ % |\medskip \\| \\ % |\qrcode[version=10]{ABCD}| \\ % |\qrcode[version=20]{ABCD}| % \end{minipage} % \end{tabular} % \end{quote} % % % \DescribeMacro{tight} % \DescribeMacro{padding} % The QR specification states that a QR code should be surrounded by white\-space % of a width equal to that of four modules. In many applications, a document % author is likely to provide sufficient spacing anyway (e.g., by placing the % QR code in a {\tt center} environment, header, or |\marginpar|), so by % default the |qrcode| package adds no spacing. If the option |padding| is % specified, however, the QR code will automatically be surrounded with 4 modules' % worth of white\-space. The key |tight| is an antonym of |padding|; the default is |tight|. % % \DescribeMacro{link} % \DescribeMacro{nolink} % \DescribeMacro{\qrcode*} % As described above, if the |hyperref| package is loaded, % then the QR codes produced in a PDF document can be made % into hyperlinks to their text. The default behavior % can be controlled with the options |nolinks| and |hyperlinks|, % but this default can be overridden for individual QR codes by invoking % the options |link| or |nolink|. % Moreover, the starred version of the macro, |\qrcode*|, is a shorthand % equivalent to |\qrcode[nolink]|. % \begin{quote} % \begin{tabular}{p{5.2cm}p{3in}} % \raggedright % \qrset{link, height=1.5cm} % \qrcode{http://www.ctan.org} % \qrcode[nolink]{This is not a URL.} % \qrcode*{Neither is this.} % & % \begin{minipage}{3in} % |\qrset{link, height=1.5cm}| \\ % |\qrcode{http://www.ctan.org}| \\ % |\qrcode[nolink]{This is not a URL.}| \\ % |\qrcode*{Neither is this.}| % \end{minipage} % \end{tabular} % \end{quote} % % \subsection{Special characters}\label{sect:specialcharacters} % Many URLs can be processed by \TeX\ with no hiccups, % but not infrequently a URL may contain the symbols |%|, |#|, % |~|, |_|, and |&|. Moreover, QR codes need not just contain % URL's, so a user may wish to encode text containing |^|, |$|, or spaces. % The |qrcode| package offers two ways of coping with these special characters. % % First, the |\qrcode| command itself processes its \meta{text to be encoded} % in a limited verbatim mode. The following characters will be encoded into % the QR code as typed: % \begin{center} % |#| |$| |&| |^| |_| |~| |%| {\tt\char32} % \end{center} % and line breaks as well.\footnote{Technically, when the input character % {\tt\char`\^\char`\^M} (CR, charcode 13) is encountered, % the character {\tt\char`\^\char`\^J} (LF, charcode 10) is placed into the QR code.} % Conspicuously absent from this list are |\|, |{|, and |}|. % This is intentional, so that macros may be used within |\qrcode| % to generate the \meta{text to be encoded} automatically. % If these characters are desired, they may be obtained by ``escaping'' them % with an extra backslash. % \begin{quote} % \begin{tabular}{p{2in}p{3in}} % \qrset{height=1.5cm}% % \qrcode{We can include #$&^_~%.} % \def\foo{bar}% % \qrcode{Set the \foo\ high.} % \qrcode{We must escape \\emph\{this\}.} % & \begin{minipage}{3in} % |\qrset{height=1.5cm}%| \\ % |\qrcode{We can include #$&^_~%.}| \\ % |\def\foo{bar}%| \\ % |\qrcode{Set the \foo\ high.}| \\ % |\qrcode{We must escape \\emph\{this\}.}| % \end{minipage} % \end{tabular} % \end{quote} % % As with all verbatim modes, however, because \TeX\ irrevocably sets catcodes % when it first encounters characters, this will not work if the |\qrcode| macro % is contained in another macro. If you call |\qrcode| inside an % |\fbox| or a |\marginpar|, for example, and if your URL contains one of those % special characters, you will either encounter error messages or (worse, because % it is undetectable to the naked eye) have the wrong QR code typeset. % In this scenario, you can still include any of the characters % |#$&^_~%|{\tt\char32}|\{}| % by escaping them with an extra backslash; % so long as they eventually pass unexpanded to |\qrcode|, % they will produce the correct QR code. % A line break may be obtained with |\?|. % \begin{quote} % \begin{tabular}{p{1.5cm}p{2in}} % \fbox{\qrcode[height=1cm]{\#\$\&\^\_\~\?\%\ \\\{\}}} % & |\fbox{qrcode[height=1cm]{\#\$\&\^\_\~\?\%\ \\\{\}}}| % \end{tabular} % \end{quote} % % \section{Limitations and Cautions} % % \begin{itemize} % \item The QR specification includes modes for encoding numeric, alphanumeric, % or Kanji data more efficiently. This package does not (yet) offer % those options. % \item The QR specification offers ways to string lengthy data across multiple % QR codes. This package does not implement that possibility. % \end{itemize} % % \StopEventually{} % % \section{Implementation} % \subsection{Key handling and options} % \begin{macrocode} %%PACKAGE LOADING \RequirePackage{xcolor}% \RequirePackage{xkeyval}% %%INITIAL CODE \newif\ifqr@draft@mode \newif\ifqr@forget@mode %%DECLARATION OF OPTIONS \define@boolkey{qr}[qr@]{draft}[true]{\ifqr@draft\qr@draft@modetrue\else\qr@draft@modefalse\fi}% \define@boolkey{qr}[qr@]{final}[true]{\ifqr@final\qr@draft@modefalse\else\qr@draft@modetrue\fi}% \define@boolkey{qr}[qr@]{forget}[true]{\ifqr@forget\qr@forget@modetrue\else\qr@forget@modefalse\fi}% \define@boolkey{qr}[qr@]{hyperlink}[true]{}% %This creates \ifqr@hyperlink. \define@boolkey{qr}[qr@]{hyperlinks}[true]{\ifqr@hyperlinks\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% \define@boolkey{qr}[qr@]{link}[true]{\ifqr@link\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% \define@boolkey{qr}[qr@]{nolink}[true]{\ifqr@nolink\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolink an antonym. \define@boolkey{qr}[qr@]{links}[true]{\ifqr@links\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% \define@boolkey{qr}[qr@]{nolinks}[true]{\ifqr@nolinks\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolinks an antonym. %%EXECUTION OF OPTIONS \qr@draft@modefalse \qr@forget@modefalse \qr@hyperlinktrue \ProcessOptionsX % \end{macrocode} % \subsection{Utilities} % \begin{macrocode} %COUNTERS \newcounter{qr@i}% \newcounter{qr@j}% \newcount\qr@a \newcount\qr@b \newcount\qr@c %BASICS \let\xa=\expandafter %This is for messages. \newlinechar=`\^^J %Tests \def\qr@relax{\relax}% %Manipulating macros \def\qr@preface@macro#1#2{% % #1 = macro name % #2 = text to add to front of macro \def\qr@tempb{#2}% \xa\xa\xa\def\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% }% \def\qr@g@preface@macro#1#2{% % #1 = macro to be appended to % #2 = code to add \edef\qr@tempb{#2}% \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb#1}% } \def\qr@getstringlength#1{% \bgroup \qr@a=0% \xdef\qr@thestring{#1}% \xa\qr@stringlength@recursive\xa(\qr@thestring\relax\relax)% \xdef\qr@stringlength{\the\qr@a}% \egroup }% \def\qr@stringlength@recursive(#1#2){% \def\qr@testi{#1}% \ifx\qr@testi\qr@relax %we are done. \let\qr@next=\relax% \else \advance\qr@a by 1% \def\qr@next{\qr@stringlength@recursive(#2)}% \fi \qr@next }% % \end{macrocode} % \subsubsection{For-loop macro} % We implement a macro |\qr@for| with the syntax % \begin{center} % |\qr@for| \meta{control sequence}=\meta{number} to \meta{number} by \meta{number} \marg{loop body} % \end{center} % The \meta{control sequence} becomes the loop variable, % which is a \TeX\ counter. % For example, |\qr@for \i=1 to 8 by 2 {\fbox{\number\i}}| % produces {\makeatletter\qr@for \i=1 to 8 by 2 {\fbox{\number\i}}}. % \begin{macrocode} %The \qr@for@depth counter measures the depth of our loop. %The outermost loop has depth zero. \newcount\qr@for@depth% \newcount\qr@for@maxdepth% \qr@for@depth=0% \qr@for@maxdepth=0% %These counters are used in the qr@for loop. \newcount\qr@for@start% \newcount\qr@for@end% \newcount\qr@for@step% %Now a macro to get a new count for every depth as needed. \def\qr@allocate@new@for@counter{% \global\advance\qr@for@maxdepth by 1% \newcount\qr@newforcount% \xa\global\xa\let\csname qr@for@var@\the\qr@for@maxdepth\endcsname=\qr@newforcount% }% \newif\ifqr@loopshouldrun %The extra # in the following definition makes sure #4 scoops up everything up to the next opening brace. %This is needed so the step can include more than one character without being enclosed in braces itself. \def\qr@for #1=#2to#3by#4#{% \qr@for@int{#1}{#2}{#3}{#4}% }% \long\def\qr@for@int#1#2#3#4#5{% \bgroup %Because we're working within a TeX group, %any values of \qr@for@start, \qr@for@end, and \qr@for@step from an outer loop %will be restored after the \egroup. % %For the \qr@for@var itself, however, we need a different counter, %because the user's text within the loop might need to access the variable from the outer loop. \advance\qr@for@depth by 1\relax% This is a local change. \ifnum\qr@for@depth>\qr@for@maxdepth% %This is the first time we have gone to this depth of nesting! %We should only be over by one. \qr@allocate@new@for@counter% \fi % \showthe\qr@for@depth% \xa\let\xa\qr@for@var\xa=\csname qr@for@var@\the\qr@for@depth\endcsname% %Now \qr@for@var points to the same register as \qr@for@var@3 or something. %The next line lets the user-level variable (e.g., \i or \j) point to the same count register. \let#1=\qr@for@var% %Now establish the looping parameters. \edef\qr@for@start@text{#2}% \edef\qr@for@end@text{#3}% \edef\qr@for@step@text{#4}% \def\qr@for@body{\bgroup #5\egroup}% \xa\qr@for@start\qr@for@start@text\relax% \xa\qr@for@end \qr@for@end@text\relax% \xa\qr@for@step \qr@for@step@text\relax% % %Next, test whether the loop should run at all. % * "\qr@for \i = 1 to 0 by 1" should fail. % * "\qr@for \i = 3 to 5 by -1" should fail. % * "\qr@for \i = 6 to 2 by 1" should fail. % * "\qr@for \i = 4 to 4 by -1" should run. % * "\qr@for \i = 4 to 4 by 1" should run. % * "\qr@for \i = 5 to 7 by 0" should fail. %The loop should fail if (step)=0 or if (step) and (end-start) have opposite signs. %The loop will fail if (step=0) or (step)*(end-start)<0. % TODO: "\qr@for \i = 5 to 5 by 0" should run (just one iteration). \qr@loopshouldruntrue \ifnum\qr@for@step=0\relax \qr@loopshouldrunfalse \fi \qr@a=\qr@for@end% \advance\qr@a by -\qr@for@start% \multiply\qr@a by \qr@for@step% \ifnum\qr@a<0\relax \qr@loopshouldrunfalse \fi \ifqr@loopshouldrun \qr@for@var=\qr@for@start% \ifnum\qr@for@step>0\relax \def\qr@for@recursive{% \qr@for@body% \advance\qr@for@var by \qr@for@step% \ifnum\qr@for@var>\qr@for@end% \let\qr@for@next=\relax% \else% \let\qr@for@next=\qr@for@recursive% \fi% \qr@for@next% }% \else \def\qr@for@recursive{% \qr@for@body% \advance\qr@for@var by \qr@for@step% \ifnum\qr@for@var<\qr@for@end% \let\qr@for@next=\relax% \else% \let\qr@for@next=\qr@for@recursive% \fi% \qr@for@next% }% \fi \qr@for@recursive% \fi \egroup }% % \end{macrocode} % \subsubsection{Base conversions} % \begin{macrocode} \def\qr@padatfront#1#2{% % #1 = macro containing text to pad % #2 = desired number of characters % Pads a number with initial zeros. \qr@getstringlength{#1}% \qr@a=\qr@stringlength\relax% \advance\qr@a by 1\relax% \qr@for \i = \qr@a to #2 by 1\relax% {\qr@g@preface@macro{#1}{0}}% } \qr@a=-1\relax% \def\qr@savehexsymbols(#1#2){% \advance\qr@a by 1\relax% \xa\def\csname qr@hexchar@\the\qr@a\endcsname{#1}% \xa\edef\csname qr@hextodecimal@#1\endcsname{\the\qr@a}% \ifnum\qr@a=15\relax %Done. \let\qr@next=\relax% \else \def\qr@next{\qr@savehexsymbols(#2)}% \fi% \qr@next% }% \qr@savehexsymbols(0123456789abcdef\relax\relax)% \def\qr@decimaltobase#1#2#3{% % #1 = macro to store result % #2 = decimal representation of a positive integer % #3 = new base \bgroup \edef\qr@newbase{#3}% \gdef\qr@base@result{}% \qr@a=#2\relax% \qr@decimaltobase@recursive% \xdef#1{\qr@base@result}% \egroup } \def\qr@decimaltobase@recursive{% \qr@b=\qr@a% \divide\qr@b by \qr@newbase\relax \multiply\qr@b by -\qr@newbase\relax \advance\qr@b by \qr@a\relax% \divide\qr@a by \qr@newbase\relax% \ifnum\qr@b<10\relax \edef\qr@newdigit{\the\qr@b}% \else \edef\qr@newdigit{\csname qr@hexchar@\the\qr@b\endcsname}% \fi \edef\qr@argument{{\noexpand\qr@base@result}{\qr@newdigit}}% \xa\qr@g@preface@macro\qr@argument% \ifnum\qr@a=0\relax \relax \else \xa\qr@decimaltobase@recursive \fi } \newcommand\qr@decimaltohex[3][0]{% % #1 (opt.) = number of hex digits to create % #2 = macro to store result % #3 = decimal digits to convert \qr@decimaltobase{#2}{#3}{16}% \qr@padatfront{#2}{#1}% } \newcommand\qr@decimaltobinary[3][0]{% % #1 (opt.) = number of bits to create % #2 = macro to store result % #3 = decimal digits to convert \qr@decimaltobase{#2}{#3}{2}% \qr@padatfront{#2}{#1}% } \qr@for \i = 0 to 15 by 1% {% \qr@decimaltohex[1]{\qr@hexchar}{\the\i}% \qr@decimaltobinary[4]{\qr@bits}{\the\i}% \xa\xdef\csname qr@b2h@\qr@bits\endcsname{\qr@hexchar}% \xa\xdef\csname qr@h2b@\qr@hexchar\endcsname{\qr@bits}% }% \newcommand\qr@binarytohex[3][\relax]{% % #1 (optional) = # digits desired % #2 = macro to save to % #3 = binary string (must be multiple of 4 bits) \def\qr@test@i{#1}% \ifx\qr@test@i\qr@relax% %No argument specified \def\qr@desireddigits{0}% \else \def\qr@desireddigits{#1}% \fi \gdef\qr@base@result{}% \edef\qr@argument{(#3\relax\relax\relax\relax\relax)}% \xa\qr@binarytohex@int\qr@argument% \qr@padatfront{\qr@base@result}{\qr@desireddigits}% \xdef#2{\qr@base@result}% } \def\qr@binarytohex@int(#1#2#3#4#5){% % #1#2#3#4 = 4 bits % #5 = remainder, including \relax\relax\relax\relax\relax terminator \def\qr@test@i{#1}% \ifx\qr@test@i\qr@relax% %Done. \def\qr@next{\relax}% \else% \xdef\qr@base@result{\qr@base@result\csname qr@b2h@#1#2#3#4\endcsname}% \def\qr@next{\qr@binarytohex@int(#5)}% \fi% \qr@next% } \newcommand\qr@hextobinary[3][\relax]{% % #1 (optional) = # bits desired % #2 = macro to save to % #3 = hexadecimal string \bgroup \def\qr@test@i{#1}% \ifx\qr@test@i\qr@relax% %No argument specified \def\qr@desireddigits{0}% \else \def\qr@desireddigits{#1}% \fi \gdef\qr@base@result{}% \edef\qr@argument{(#3\relax\relax)}% \xa\qr@hextobinary@int\qr@argument% \qr@padatfront{\qr@base@result}{\qr@desireddigits}% \xdef#2{\qr@base@result}% \egroup } \def\qr@hextobinary@int(#1#2){% % #1 = hexadecimal character % #2 = remainder, including \relax\relax terminator \def\qr@test@@i{#1}% \ifx\qr@test@@i\qr@relax% %Done. \def\qr@next{\relax}% \else% \xdef\qr@base@result{\qr@base@result\csname qr@h2b@#1\endcsname}% \def\qr@next{\qr@hextobinary@int(#2)}% \fi% \qr@next% } \def\qr@hextodecimal#1#2{% \edef\qr@argument{#2}% \xa\qr@a\xa=\xa\number\xa"\qr@argument\relax% \edef#1{\the\qr@a}% } \def\qr@hextodecimal#1#2{% % #1 = macro to store result % #2 = hexadecimal representation of a positive integer \bgroup \qr@a=0\relax% \edef\qr@argument{(#2\relax)}% \xa\qr@hextodecimal@recursive\qr@argument% \xdef#1{\the\qr@a}% \egroup } \def\qr@hextodecimal@recursive(#1#2){% % #1 = first hex char % #2 = remainder \advance \qr@a by \csname qr@hextodecimal@#1\endcsname\relax% \edef\qr@testii{#2}% \ifx\qr@testii\qr@relax% %Done. \let\qr@next=\relax% \else %There's at least one more digit. \multiply\qr@a by 16\relax \edef\qr@next{\noexpand\qr@hextodecimal@recursive(#2)}% \fi% \qr@next% } % \end{macrocode} % \subsubsection{Catcode setup} % \begin{macrocode} %The following catcode trickery creates special characters %with catcode 12 (other) for use in our verbatim handling. {\catcode`\ =12\relax\gdef\qr@otherspace{ }}% {\catcode`\%=12\relax\gdef\qr@otherpercent{%}}% {\catcode`\#=12\relax\gdef\qr@otherpound{#}}% {\catcode`\|=0\relax|catcode`|\=12|relax|gdef|qr@otherbackslash{\}}% {\catcode`\^^J=12\relax\gdef\qr@otherlf{^^J}}% \bgroup \catcode`\<=1\relax \catcode`\>=2\relax \catcode`\{=12\relax\gdef\qr@otherleftbrace<{>% \catcode`\}=12\relax\gdef\qr@otherrightbrace<}>% \egroup% {\catcode`\&=12\relax\gdef\qr@otherampersand{&}}% {\catcode`\~=12\relax\gdef\qr@othertilde{~}}% {\catcode`\^=12\relax\gdef\qr@othercaret{^}}% {\catcode`\_=12\relax\gdef\qr@otherunderscore{_}}% {\catcode`\$=12\relax\gdef\qr@otherdollar{$}}% %Line feeds require some special handling. \TeX\ reads a line feed in the input %as |^^M| (carriage return, character code 13), but it should be encoded in a %QR code as |^^J| (line feed, character code 10). %To do this, we make |^^M| an active character and a synonym for a |^^J| with catcode 12. %Note that the macro |\qr@verbatimlinefeeds| must itself be processed with |^^M| active. {\catcode`\^^M=13\relax\gdef\qr@verbatimlinefeeds{\let^^M=\qr@otherlf}} \def\qr@verbatimcatcodes{% \catcode`\#=12\relax \catcode`\$=12\relax \catcode`\&=12\relax \catcode`\^=12\relax \catcode`\_=12\relax \catcode`\~=12\relax \catcode`\%=12\relax \catcode`\ =12\relax \catcode`\^^M=13\relax\qr@verbatimlinefeeds}% \def\qr@setescapedspecials{% \let\ =\qr@otherspace% \let\%=\qr@otherpercent% \let\#=\qr@otherpound% \let\&=\qr@otherampersand% \let\^=\qr@othercaret% \let\_=\qr@otherunderscore% \let\~=\qr@othertilde% \let\$=\qr@otherdollar% \let\\=\qr@otherbackslash% \let\{=\qr@otherleftbrace% \let\}=\qr@otherrightbrace% \let\?=\qr@otherlf% }% % \end{macrocode} % \subsection{Plotting} % \begin{macrocode} \def\qr@creatematrix#1{% \xa\gdef\csname #1\endcsname##1##2{% \csname #1@##1@##2\endcsname }% }% \def\qr@storetomatrix#1#2#3#4{% % #1 = matrix name % #2 = row number % #3 = column number % #4 = value of matrix entry \xa\gdef\csname #1@#2@#3\endcsname{#4}% }% \def\qr@estoretomatrix#1#2#3#4{% % This version performs exactly one expansion on #4. % #1 = matrix name % #2 = row number % #3 = column number % #4 = value of matrix \xa\xa\xa\gdef\xa\xa\csname #1@#2@#3\endcsname\xa{#4}% }% \def\qr@matrixentry#1#2#3{% % #1 = matrix name % #2 = row number % #3 = column number \csname #1@#2@#3\endcsname% }% \def\qr@createsquareblankmatrix#1#2{% \qr@creatematrix{#1}% \xa\gdef\csname #1@numrows\endcsname{#2}% \xa\gdef\csname #1@numcols\endcsname{#2}% \qr@for \i = 1 to #2 by 1% {\qr@for \j = 1 to #2 by 1% {\qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@blank}}}% }% \def\qr@numberofrowsinmatrix#1{% \csname #1@numrows\endcsname% }% \def\qr@numberofcolsinmatrix#1{% \csname #1@numcols\endcsname% }% \def\qr@setnumberofrows#1#2{% \xa\xdef\csname #1@numrows\endcsname{#2}% }% \def\qr@setnumberofcols#1#2{% \xa\xdef\csname #1@numcols\endcsname{#2}% }% \newlength\qr@desiredheight \setlength\qr@desiredheight{2cm}% \newlength\qr@modulesize \newlength\qr@minipagewidth \def\qr@printmatrix#1{% \def\qr@black{\rule{\qr@modulesize}{\qr@modulesize}}% \def\qr@white{\rule{\qr@modulesize}{0pt}}% \def\qr@black@fixed{\rule{\qr@modulesize}{\qr@modulesize}}% \def\qr@white@fixed{\rule{\qr@modulesize}{0pt}}% \def\qr@black@format{\rule{\qr@modulesize}{\qr@modulesize}}% \def\qr@white@format{\rule{\qr@modulesize}{0pt}}% %Set module size \setlength{\qr@modulesize}{\qr@desiredheight}% \divide\qr@modulesize by \qr@size\relax% % \setlength{\qr@minipagewidth}{\qr@modulesize}% \multiply\qr@minipagewidth by \qr@size\relax% \ifqr@tight \else \advance\qr@minipagewidth by 8\qr@modulesize% \fi \begin{minipage}{\qr@minipagewidth}% \baselineskip=\qr@modulesize% \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. \qr@for \i = 1 to \qr@numberofrowsinmatrix{#1} by 1% {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. \qr@for \j = 1 to \qr@numberofcolsinmatrix{#1} by 1% {\qr@matrixentry{#1}{\the\i}{\the\j}}% \par}% \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% \end{minipage}% }% \def\qr@printsavedbinarymatrix#1{% \edef\qr@binarystring{#1\relax\relax}% %Set module size \setlength{\qr@modulesize}{\qr@desiredheight}% \divide\qr@modulesize by \qr@size\relax% % \setlength{\qr@minipagewidth}{\qr@modulesize}% \multiply\qr@minipagewidth by \qr@size\relax% \ifqr@tight \else \advance\qr@minipagewidth by 8\qr@modulesize% \fi \begin{minipage}{\qr@minipagewidth}% \baselineskip=\qr@modulesize% \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. \qr@for \i = 1 to \qr@size by 1% {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. \qr@for \j = 1 to \qr@size by 1% {\edef\qr@theargument{(\qr@binarystring)}% \xa\qr@printsavedbinarymatrix@int\qr@theargument }% \par}% \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% \end{minipage}% }% \def\qr@printsavedbinarymatrix@int(#1#2){% % #1 = first bit, either 1 or 0. % #2 = remainder of string, terminating with \relax\relax % There's no need to check for EOF here, because % we'll only call this n^2 times. \ifcase #1\relax \rule{\qr@modulesize}{0pt}% % 0: white square \or \rule{\qr@modulesize}{\qr@modulesize}% % 1: black square \fi \xdef\qr@binarystring{#2}% }% \def\qr@createliteralmatrix#1#2#3{% % #1 = matrix name % #2 = m, the number of rows and columns in the square matrix % #3 = a string of m^2 tokens to be written into the matrix \qr@creatematrix{#1}% \xa\xdef\csname #1@numrows\endcsname{#2}% \xa\xdef\csname #1@numcols\endcsname{#2}% \gdef\qr@literalmatrix@tokens{#3}% \qr@for \i = 1 to #2 by 1% {\qr@for \j = 1 to #2 by 1% {\xa\qr@createliteralmatrix@int\xa(\qr@literalmatrix@tokens)% \qr@estoretomatrix{#1}{\the\i}{\the\j}{\qr@entrytext}% }% }% } \def\qr@createliteralmatrix@int(#1#2){% \def\qr@entrytext{#1}% \gdef\qr@literalmatrix@tokens{#2}% } \qr@createliteralmatrix{finderpattern}{8}{% \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% \qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed% }% \qr@createliteralmatrix{alignmentpattern}{5}{% \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed% \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% }% \def\qr@copymatrixentry#1#2#3#4#5#6{% % Copy the (#2,#3) entry of matrix #1 % to the (#5,#6) position of matrix #4. \xa\xa\xa\global% \xa\xa\xa\let\xa\xa\csname #4@#5@#6\endcsname% \csname #1@#2@#3\endcsname% }% \def\qr@createduplicatematrix#1#2{% % #1 = name of copy % #2 = original matrix to be copied \qr@creatematrix{#1}% \qr@for \i = 1 to \qr@numberofrowsinmatrix{#2} by 1% {\qr@for \j = 1 to \qr@numberofcolsinmatrix{#2} by 1% {\qr@copymatrixentry{#2}{\the\i}{\the\j}{#1}{\the\i}{\the\j}% }% }% \qr@setnumberofrows{#1}{\qr@numberofrowsinmatrix{#2}}% \qr@setnumberofcols{#1}{\qr@numberofcolsinmatrix{#2}}% }% \def\qr@placefinderpattern@int#1#2#3#4#5{% % Work on matrix #1. % Start in position (#2, #3) -- should be a corner % #4 indicates horizontal direction (1=right, -1=left) % #5 indicates vertical direction (1=down, -1=up) % % In this code, \sourcei and \sourcej are TeX counts working through the finderpattern matrix, % and i and j are LaTeX counters indicating positions in the big matrix. \setcounter{qr@i}{#2}% \qr@for \sourcei=1 to 8 by 1% {\setcounter{qr@j}{#3}% \qr@for \sourcej=1 to 8 by 1% {\qr@copymatrixentry{finderpattern}{\the\sourcei}{\the\sourcej}% {#1}{\theqr@i}{\theqr@j}% \addtocounter{qr@j}{#5}% }% \addtocounter{qr@i}{#4}% }% }% \def\qr@placefinderpatterns#1{% % #1=matrix name \qr@placefinderpattern@int{#1}{1}{1}{1}{1}% \qr@placefinderpattern@int{#1}{\qr@numberofrowsinmatrix{#1}}{1}{-1}{1}% \qr@placefinderpattern@int{#1}{1}{\qr@numberofcolsinmatrix{#1}}{1}{-1}% }% \def\qr@placetimingpatterns#1{% %Set \qr@endingcol to n-8. \qr@a=\qr@size\relax% \advance\qr@a by -8\relax% \edef\qr@endingcol{\the\qr@a}% \qr@for \j = 9 to \qr@endingcol by 1% {\ifodd\j\relax% \qr@storetomatrix{#1}{7}{\the\j}{\qr@black@fixed}% \qr@storetomatrix{#1}{\the\j}{7}{\qr@black@fixed}% \else% \qr@storetomatrix{#1}{7}{\the\j}{\qr@white@fixed}% \qr@storetomatrix{#1}{\the\j}{7}{\qr@white@fixed}% \fi% }% }% \def\qr@placealignmentpattern@int#1#2#3{% % Work on matrix #1. % Write an alignment pattern into the matrix, centered on (#2,#3). \qr@a=#2\relax% \advance\qr@a by -2\relax% \qr@b=#3\relax% \advance\qr@b by -2\relax% \setcounter{qr@i}{\the\qr@a}% \qr@for \i=1 to 5 by 1% {\setcounter{qr@j}{\the\qr@b}% \qr@for \j=1 to 5 by 1% {\qr@copymatrixentry{alignmentpattern}{\the\i}{\the\j}% {#1}{\theqr@i}{\theqr@j}% \stepcounter{qr@j}% }% \stepcounter{qr@i}% }% }% \newif\ifqr@incorner% \def\qr@placealignmentpatterns#1{% %There are k^2-3 alignment patterns, %arranged in a (k x k) grid within the matrix. %They begin in row 7, column 7, %except that the ones in the NW, NE, and SW corners %are omitted because of the finder patterns. %Recall that % * \qr@k stores k, % * \qr@alignment@firstskip stores how far between the 1st and 2nd row/col, & % * \qr@alignment@generalskip stores how far between each subsequent row/col. \xa\ifnum\qr@k>0\relax %There will be at least one alignment pattern. %N.B. k cannot equal 1. \xa\ifnum\qr@k=2\relax % 2*2-3 = exactly 1 alignment pattern. \qr@a=7\relax \advance\qr@a by \qr@alignment@firstskip\relax \xdef\qr@target@ii{\the\qr@a}% \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@ii}% \else % k is at least 3, so the following loops should be safe. \xdef\qr@target@ii{7}% \qr@for \ii = 1 to \qr@k by 1% {\ifcase\ii\relax% \relax% \ii should never equal 0. \or \xdef\qr@target@ii{7}% If \ii = 1, we start in row 7. \or %If \ii = 2, we add the firstskip. \qr@a=\qr@target@ii\relax% \advance\qr@a by \qr@alignment@firstskip\relax% \xdef\qr@target@ii{\the\qr@a}% \else %If \ii>2, we add the generalskip. \qr@a=\qr@target@ii\relax% \advance\qr@a by \qr@alignment@generalskip\relax% \xdef\qr@target@ii{\the\qr@a}% \fi \qr@for \jj = 1 to \qr@k by 1% {\ifcase\jj\relax% \relax% \jj should never equal 0. \or \xdef\qr@target@jj{7}% If \jj=1, we start in row 7. \or %If \jj=2, we add the firstskip. \qr@a=\qr@target@jj\relax% \advance\qr@a by \qr@alignment@firstskip% \xdef\qr@target@jj{\the\qr@a}% \else %If \jj>2, we add the generalskip. \qr@a=\qr@target@jj\relax% \advance\qr@a by \qr@alignment@generalskip% \xdef\qr@target@jj{\the\qr@a}% \fi \qr@incornerfalse% \ifnum\ii=1\relax \ifnum\jj=1\relax \qr@incornertrue \else \ifnum\qr@k=\jj\relax \qr@incornertrue \fi \fi \else \xa\ifnum\qr@k=\ii\relax \ifnum\jj=1\relax \qr@incornertrue \fi \fi \fi \ifqr@incorner \relax \else \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@jj}% \fi }% ends \qr@for \jj }% ends \qr@for \ii \fi \fi }% \def\qr@placedummyformatpatterns#1{% \qr@for \j = 1 to 9 by 1% {\ifnum\j=7\relax% \else% \qr@storetomatrix{#1}{9}{\the\j}{\qr@format@square}% \qr@storetomatrix{#1}{\the\j}{9}{\qr@format@square}% \fi% }% \setcounter{qr@j}{\qr@size}% \qr@for \j = 1 to 8 by 1% {\qr@storetomatrix{#1}{9}{\theqr@j}{\qr@format@square}% \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@format@square}% \addtocounter{qr@j}{-1}% }% %Now go back and change the \qr@format@square in (n-8,9) to \qr@black@fixed. \addtocounter{qr@j}{1}% \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@black@fixed}% }% \def\qr@placedummyversionpatterns#1{% \xa\ifnum\qr@version>6\relax %Must include version information. \global\c@qr@i=\qr@size% \global\advance\c@qr@i by -10\relax% \qr@for \i = 1 to 3 by 1% {\qr@for \j = 1 to 6 by 1% {\qr@storetomatrix{#1}{\theqr@i}{\the\j}{\qr@format@square}% \qr@storetomatrix{#1}{\the\j}{\theqr@i}{\qr@format@square}% }% \stepcounter{qr@i}% }% \fi }% \def\qr@writebit(#1#2)#3{% % #3 = matrix name % (qr@i,qr@j) = position to write in (LaTeX counters) % #1 = bit to be written % #2 = remaining bits plus '\relax' as an end-of-file marker \edef\qr@datatowrite{#2}% \ifnum#1=1 \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@black}% \else \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@white}% \fi }% \newif\ifqr@rightcol \newif\ifqr@goingup \def\qr@writedata@hex#1#2{% % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. % #2 = a string consisting of bytes to write into the matrix, in two-char hex format. \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% \qr@rightcoltrue% \qr@goinguptrue% \edef\qr@argument{{#1}(#2\relax\relax\relax)}% \xa\qr@writedata@hex@recursive\qr@argument% }% \def\qr@writedata@hex@recursive#1(#2#3#4){% % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. % (qr@i,qr@j) = position to write in LaTeX counters % #2#3#4 contains the hex codes of the bytes to be written, plus \relax\relax\relax % as an end-of-file marker \edef\qr@testii{#2}% \ifx\qr@testii\qr@relax% % #2 is \relax, so there is nothing more to write. \relax \let\qr@next=\relax \else % #2 is not \relax, so there is another byte to write. \qr@hextobinary[8]{\bytetowrite}{#2#3}% \xdef\qr@datatowrite{\bytetowrite\relax}% %Add terminating "\relax" \qr@writedata@recursive{#1}% %This function actually writes the 8 bits. \edef\qr@argument{{#1}(#4)}% \xa\def\xa\qr@next\xa{\xa\qr@writedata@hex@recursive\qr@argument}% %Call self to write the next bit. \fi \qr@next }% \def\qr@writedata#1#2{% % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. % #2 = a string consisting of 0's and 1's to write into the matrix. \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% \qr@rightcoltrue \qr@goinguptrue \edef\qr@datatowrite{#2\relax}% \qr@writedata@recursive{#1}% }% \def\qr@@blank{\qr@blank}% \def\qr@writedata@recursive#1{% % #1 = matrix name % (qr@i,qr@j) = position to write in (LaTeX counters) % \qr@datatowrite contains the bits to be written, plus '\relax' as an end-of-file marker \xa\let\xa\squarevalue\csname #1@\theqr@i @\theqr@j\endcsname% \ifx\squarevalue\qr@@blank %Square is blank, so write data in it. \xa\qr@writebit\xa(\qr@datatowrite){#1}% %The \qr@writebit macro not only writes the first bit of \qr@datatowrite into the matrix, %but also removes the bit from the 'bitstream' of \qr@datatowrite. \fi %Now adjust our position in the matrix. \ifqr@rightcol %From the right-hand half of the two-bit column, we always move left. Easy peasy. \addtocounter{qr@j}{-1}% \qr@rightcolfalse \else %If we're in the left-hand column, things are harder. \ifqr@goingup %First, suppose we're going upwards. \ifnum\c@qr@i>1\relax% %If we're not in the first row, things are easy. %We move one to the right and one up. \addtocounter{qr@j}{1}% \addtocounter{qr@i}{-1}% \qr@rightcoltrue \else %If we are in the first row, then we move to the left, %and we are now in the right-hand column on a downward pass. \addtocounter{qr@j}{-1}% \qr@goingupfalse \qr@rightcoltrue \fi \else %Now, suppose we're going downwards. \xa\ifnum\qr@size>\c@qr@i\relax% %If we're not yet in the bottom row, things are easy. %We move one to the right and one down. \addtocounter{qr@j}{1}% \addtocounter{qr@i}{1}% \qr@rightcoltrue \else %If we are in the bottom row, then we move to the left, %and we are now in the right-hand column on an upward pass. \addtocounter{qr@j}{-1}% \qr@rightcoltrue \qr@goinguptrue \fi \fi %One problem: what if we just moved into the 7th column? %Das ist verboten. %If we just moved (left) into the 7th column, we should move on into the 6th column. \ifnum\c@qr@j=7\relax% \setcounter{qr@j}{6}% \fi \fi %Now check whether there are any more bits to write. \ifx\qr@datatowrite\qr@relax % \qr@datatowrite is just `\relax', so we're done. \let\qr@next=\relax \relax \else % Write some more! \def\qr@next{\qr@writedata@recursive{#1}}% \fi \qr@next }% \def\qr@writeremainderbits#1{% % #1 = name of a matrix that has been prepared and partly filled. % (qr@i,qr@j) = position to write in LaTeX counters \xa\ifnum\qr@numremainderbits>0\relax \def\qr@datatowrite{}% \qr@for \i = 1 to \qr@numremainderbits by 1% {\g@addto@macro{\qr@datatowrite}{0}}% \g@addto@macro{\qr@datatowrite}{\relax}% terminator \qr@writedata@recursive{#1}% \fi }% \newif\ifqr@cellinmask \def\qr@setmaskingfunction#1{% % #1 = 1 decimal digit for the mask. (I see no reason to use the 3-bit binary code.) % The current position is (\themaski,\themaskj), with indexing starting at 0. \edef\qr@maskselection{#1}% \xa\ifcase\qr@maskselection\relax %Case 0: checkerboard \def\qr@parsemaskingfunction{% % Compute mod(\themaski+\themaskj,2)% \qr@a=\c@maski% \advance\qr@a by \c@maskj% \qr@b=\qr@a% \divide\qr@b by 2% \multiply\qr@b by 2% \advance\qr@a by -\qr@b% \edef\qr@maskfunctionresult{\the\qr@a}% }% \or %Case 1: horizontal stripes \def\qr@parsemaskingfunction{% % Compute mod(\themaski,2)% \ifodd\c@maski\relax% \def\qr@maskfunctionresult{1}% \else% \def\qr@maskfunctionresult{0}% \fi% }% \or %Case 2: vertical stripes \def\qr@parsemaskingfunction{% % Compute mod(\themaskj,3)% \qr@a=\c@maskj% \divide\qr@a by 3% \multiply\qr@a by 3% \advance\qr@a by -\c@maskj% \edef\qr@maskfunctionresult{\the\qr@a}% }% \or %Case 3: diagonal stripes \def\qr@parsemaskingfunction{% % Compute mod(\themaski+\themaskj,3)% \qr@a=\c@maski% \advance\qr@a by \c@maskj% \qr@b=\qr@a% \divide\qr@b by 3% \multiply\qr@b by 3% \advance\qr@b by -\qr@a% \edef\qr@maskfunctionresult{\the\qr@b}% }% \or %Case 4: wide checkerboard \def\qr@parsemaskingfunction{% % Compute mod(floor(\themaski/2) + floor(\themaskj/3),2) % \qr@a=\c@maski% \divide\qr@a by 2% \qr@b=\c@maskj% \divide\qr@b by 3% \advance\qr@a by \qr@b% \qr@b=\qr@a% \divide\qr@a by 2% \multiply\qr@a by 2% \advance\qr@a by -\qr@b% \edef\qr@maskfunctionresult{\the\qr@a}% }% \or %Case 5: quilt \def\qr@parsemaskingfunction{% % Compute mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) % \qr@a=\c@maski% \multiply\qr@a by \c@maskj% \qr@b=\qr@a% \qr@c=\qr@a% \divide\qr@a by 2% \multiply\qr@a by 2% \advance\qr@a by -\qr@c% (result will be -mod(i*j,2), which is negative.) \divide\qr@b by 3% \multiply\qr@b by 3% \advance\qr@b by -\qr@c% (result will be -mod(i*j,3), which is negative.) \advance\qr@a by \qr@b% (result is negative of what's in the spec.) \edef\qr@maskfunctionresult{\the\qr@a}% }% \or %Case 6: arrows \def\qr@parsemaskingfunction{% % Compute mod( mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % \qr@a=\c@maski% \multiply\qr@a by \c@maskj% \qr@b=\qr@a% \qr@c=\qr@a% \multiply\qr@c by 2% % \qr@c equals 2*i*j. \divide\qr@a by 2% \multiply\qr@a by 2% \advance\qr@c by -\qr@a% Now \qr@c equals i*j + mod(i*j,2). \divide\qr@b by 3% \multiply\qr@b by 3% \advance\qr@c by -\qr@b% (Now \qr@c equals mod(i*j,2) + mod(i*j,3). \qr@a=\qr@c% \divide\qr@a by 2% \multiply\qr@a by 2% \advance\qr@c by-\qr@a% \edef\qr@maskfunctionresult{\the\qr@c}% }% \or %Case 7: shotgun \def\qr@parsemaskingfunction{% % Compute mod( mod(\themaski+\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % \qr@a=\c@maski% \advance\qr@a by \c@maskj% %So \qr@a = i+j \qr@b=\c@maski% \multiply\qr@b by \c@maskj% %So \qr@b = i*j \qr@c=\qr@a% \advance\qr@c by \qr@b% So \qr@c = i+j+i*j \divide\qr@a by 2% \multiply\qr@a by 2% \advance\qr@c by -\qr@a% So \qr@c = mod(i+j,2) + i*j \divide\qr@b by 3% \multiply\qr@b by 3% \advance\qr@c by -\qr@b% So \qr@c = mod(i+j,2) + mod(i*j,3) \qr@a=\qr@c% \divide\qr@c by 2% \multiply\qr@c by 2% \advance\qr@a by -\qr@c% \edef\qr@maskfunctionresult{\the\qr@a}% }% \fi }% \def\qr@checkifcellisinmask{% % The current position is (\i,\j), in TeX counts, % but the LaTeX counters (maski,maskj) should contain % the current position with indexing starting at 0. % That is, maski = \i-1 and maskj = \j-1. % % \qr@parsemaskingfunction must have been set by a call to \qr@setmaskingfunction \qr@parsemaskingfunction \xa\ifnum\qr@maskfunctionresult=0\relax \qr@cellinmasktrue \else \qr@cellinmaskfalse \fi }% \newcounter{maski}% \newcounter{maskj}% \def\qr@applymask#1#2#3{% % #1 = name of a matrix that should be filled out completely % except for the format and/or version information. % #2 = name of a new matrix to contain the masked version % #3 = 1 decimal digit naming the mask \qr@createduplicatematrix{#2}{#1}% \qr@setmaskingfunction{#3}% \setcounter{maski}{-1}% \qr@for \i = 1 to \qr@size by 1% {\stepcounter{maski}% \setcounter{maskj}{-1}% \qr@for \j = 1 to \qr@size by 1% {\stepcounter{maskj}% \qr@checkifcellisinmask \ifqr@cellinmask \qr@checkifcurrentcellcontainsdata{#2}% \ifqr@currentcellcontainsdata \qr@flipcurrentcell{#2}% \fi \fi }% }% }% \newif\ifqr@currentcellcontainsdata \qr@currentcellcontainsdatafalse \def\qr@@white{\qr@white}% \def\qr@@black{\qr@black}% \def\qr@checkifcurrentcellcontainsdata#1{% % #1 = name of matrix \qr@currentcellcontainsdatafalse \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white \qr@currentcellcontainsdatatrue \fi \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@black \qr@currentcellcontainsdatatrue \fi }% \def\qr@flipped@black{\qr@black}% \def\qr@flipped@white{\qr@white}% \def\qr@flipcurrentcell#1{% % #1 = name of matrix % (\i, \j) = current position, in TeX counts. % This assumes the cell contains data, either black or white! \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@black}% \else \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@white}% \fi }% \def\qr@chooseandapplybestmask#1{% % #1 = name of a matrix that should be filled out completely % except for the format and/or version information. % This function applies all eight masks in succession, % calculates their penalties, and remembers the best. % The number indicating which mask was used is saved in \qr@mask@selected. \qr@createduplicatematrix{originalmatrix}{#1}% \message{^^J}% \gdef\qr@currentbestmask{0}% \qr@for \i = 1 to 7 by 1% {\message{^^J}% \xa\xa\xa\ifnum\xa\qr@penalty\xa<\qr@currentbestpenalty\relax %We found a better mask. \xdef\qr@currentbestmask{\the\i}% \qr@createduplicatematrix{#1}{currentmasked}% \xdef\qr@currentbestpenalty{\qr@penalty}% \fi }% \xdef\qr@mask@selected{\qr@currentbestmask}% \message{^^J}% }% \def\qr@Ni{3}% \def\qr@Nii{3}% \def\qr@Niii{40}% \def\qr@Niv{10}% \def\qr@fiveones{11111}% \def\qr@fivezeros{11111}% \def\qr@twoones{11}% \def\qr@twozeros{00}% \def\qr@finderA{00001011101}% \def\qr@finderB{10111010000}% \def\qr@finderB@three{1011101000}% \def\qr@finderB@two{101110100}% \def\qr@finderB@one{10111010}% \def\qr@finderB@zero{1011101}% \newif\ifqr@stringoffive \def\qr@addpenaltyiii{% \addtocounter{penaltyiii}{\qr@Niii}% }% \newcounter{totalones}% \newcounter{penaltyi}% \newcounter{penaltyii}% \newcounter{penaltyiii}% \newcounter{penaltyiv}% \def\qr@evaluatemaskpenalty#1{% % #1 = name of a matrix that we will test for the penalty % according to the specs. \setcounter{penaltyi}{0}% \setcounter{penaltyii}{0}% \setcounter{penaltyiii}{0}% \setcounter{penaltyiv}{0}% \bgroup%localize the meanings we give to the symbols \def\qr@black{1}\def\qr@white{0}% \def\qr@black@fixed{1}\def\qr@white@fixed{0}% \def\qr@format@square{0}% This is not stated in the specs, but seems % to be the standard implementation. \def\qr@blank{0}% These would be any bits at the end. % \setcounter{totalones}{0}% \qr@for \i=1 to \qr@size by 1% {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. \qr@stringoffivefalse \def\qr@lasttwo@thisrow{z}% %The z is a dummy. \def\qr@lasttwo@nextrow{z}% %The z is a dummy. \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. \def\qr@ignore@finderB@at{0}% \qr@for \j=1 to \qr@size by 1% {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% % % LASTFIVE CODE FOR PENALTY 1 % First, add the new bit to the end. \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% \ifnum\j<5\relax% %Not yet on the 5th entry. %Don't do any testing. \else % 5th entry or later. % Remove the old one, and then test. \qr@removefirsttoken\qr@lastfive% \ifx\qr@lastfive\qr@fiveones% \ifqr@stringoffive% %This is a continuation of a previous block of five or more 1's. \stepcounter{penaltyi}% \else %This is a new string of five 1's. \addtocounter{penaltyi}{\qr@Ni}% \global\qr@stringoffivetrue \fi \else \ifx\qr@lastfive\qr@fivezeros% \ifqr@stringoffive %This is a continuation of a previous block of five or more 0's. \stepcounter{penaltyi}% \else %This is a new string of five 0's. \addtocounter{penaltyi}{\qr@Ni}% \global\qr@stringoffivetrue \fi \else %This is not a string of five 1's or five 0's. \global\qr@stringoffivefalse \fi \fi \fi % % 2x2 BLOCKS FOR PENALTY 2 % Every 2x2 block of all 1's counts for \qr@Nii penalty points. % We do not need to run this test in the last row. \xa\ifnum\xa\i\xa<\qr@size\relax \xa\g@addto@macro\xa\qr@lasttwo@thisrow\xa{\qr@newbit}% %Compute \qr@iplusone \qr@a=\i\relax% \advance\qr@a by 1% \edef\qr@iplusone{\the\qr@a}% % \edef\qr@nextrowbit{\qr@matrixentry{#1}{\qr@iplusone}{\the\j}}% \xa\g@addto@macro\xa\qr@lasttwo@nextrow\xa{\qr@nextrowbit}% \ifnum\j<2\relax% %Still in the first column; no check. \else %Second column or later. Remove the old bits, and then test. \qr@removefirsttoken\qr@lasttwo@thisrow \qr@removefirsttoken\qr@lasttwo@nextrow \ifx\qr@lasttwo@thisrow\qr@twoones \ifx\qr@lasttwo@nextrow\qr@twoones \addtocounter{penaltyii}{\qr@Nii}% \fi \else \ifx\qr@lasttwo@thisrow\qr@twozeros \ifx\qr@lasttwo@nextrow\qr@twozeros \addtocounter{penaltyii}{\qr@Nii}% \fi \fi \fi \fi \fi % % LASTNINE CODE FOR PENALTY 3 % First, add the new bit to the end. \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% \ifnum\j<7\relax% %Not yet on the 7th entry. %Don't do any testing. \else % 7th entry or later. % Remove the old one, and then test. \qr@removefirsttoken\qr@lastnine \xa\ifnum\qr@size=\j\relax% % Last column. Any of the following should count: % 1011101 (\qr@finderB@zero) % 10111010 (\qr@finderB@one) % 101110100 (\qr@finderB@two) % 1011101000 (\qr@finderB@three) % 10111010000 (\qr@finderB) \ifx\qr@lastnine\qr@finderB \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@three \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@two \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@one \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@zero \qr@addpenaltyiii \fi \fi \fi \fi \fi \else \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 \qr@addpenaltyiii %Also, we record our discovery, so that we can't count this pattern again %if it shows up four columns later as 1011101 0000. % %Set \qr@ignore@finderB@at to \j+4. \qr@a=\j\relax% \advance\qr@a by 4% \xdef\qr@ignore@finderB@at{\the\qr@a}% \else \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. \xa\ifnum\qr@ignore@finderB@at=\j\relax %This pattern was *not* counted already earlier. \qr@addpenaltyiii \fi \fi \fi \fi \fi % %COUNT 1's FOR PENALTY 4 \xa\ifnum\qr@newbit=1\relax% \stepcounter{totalones}% \fi }% end of j-loop }% end of i-loop % %NOW WE ALSO NEED TO RUN DOWN THE COLUMNS TO FINISH CALCULATING PENALTIES 1 AND 3. \qr@for \j=1 to \qr@size by 1% {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. \qr@stringoffivefalse \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. \def\qr@ignore@finderB@at{0}% \qr@for \i=1 to \qr@size by 1% {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% % % LASTFIVE CODE FOR PENALTY 1 % First, add the new bit to the end. \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% \ifnum\i<5\relax% %Not yet on the 5th entry. %Don't do any testing. \else % 5th entry or later. % Remove the old one, and then test. \qr@removefirsttoken\qr@lastfive% \ifx\qr@lastfive\qr@fiveones% \ifqr@stringoffive% %This is a continuation of a previous block of five or more 1's. \stepcounter{penaltyi}% \else %This is a new string of five 1's. \addtocounter{penaltyi}{\qr@Ni}% \global\qr@stringoffivetrue \fi \else \ifx\qr@lastfive\qr@fivezeros% \ifqr@stringoffive %This is a continuation of a previous block of five or more 0's. \stepcounter{penaltyi}% \else %This is a new string of five 0's. \addtocounter{penaltyi}{\qr@Ni}% \global\qr@stringoffivetrue \fi \else %This is not a string of five 1's or five 0's. \global\qr@stringoffivefalse \fi \fi \fi % % HAPPILY, WE DON'T NEED TO CALCULATE PENALTY 2 AGAIN. % % LASTNINE CODE FOR PENALTY 3 % First, add the new bit to the end. \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% \ifnum\i<7\relax% %Not yet on the 7th entry. %Don't do any testing. \else % 7th entry or later. % Remove the old one, and then test. \qr@removefirsttoken\qr@lastnine \xa\ifnum\qr@size=\i\relax% % Last column. Any of the following should count: % 1011101 (\qr@finderB@zero) % 10111010 (\qr@finderB@one) % 101110100 (\qr@finderB@two) % 1011101000 (\qr@finderB@three) % 10111010000 (\qr@finderB) \ifx\qr@lastnine\qr@finderB \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@three \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@two \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@one \qr@addpenaltyiii \else \qr@removefirsttoken\qr@lastnine \ifx\qr@lastnine\qr@finderB@zero \qr@addpenaltyiii \fi \fi \fi \fi \fi \else \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 \qr@addpenaltyiii %Also, we record our discovery, so that we can't count this pattern again %if it shows up four columns later as 1011101 0000. % %Set \qr@ignore@finderB@at to \i+4. \qr@a=\i\relax% \advance\qr@a by 4% \xdef\qr@ignore@finderB@at{\the\qr@a}% \else \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. \xa\ifnum\qr@ignore@finderB@at=\i\relax %This pattern was *not* counted already earlier. \qr@addpenaltyiii \fi \fi \fi \fi \fi % }% end of i-loop }% end of j-loop \egroup% % %CALCULATE PENALTY 4 %According to the spec, penalty #4 is computed as % floor( |(i/n^2)-0.5|/0.05 ) % where i is the total number of 1's in the matrix. % This is equal to abs(20*i-10n^2) div n^2. % \qr@a=\c@totalones\relax \multiply\qr@a by 20\relax \qr@b=\qr@size\relax \multiply\qr@b by \qr@size\relax \qr@c=10\relax \multiply\qr@c by \qr@b\relax \advance\qr@a by -\qr@c\relax \ifnum\qr@a<0\relax \multiply\qr@a by -1\relax \fi \divide\qr@a by \qr@b\relax \setcounter{penaltyiv}{\the\qr@a}% % %CALCULATE TOTAL PENALTY \qr@a=\thepenaltyi\relax% \advance\qr@a by \thepenaltyii\relax% \advance\qr@a by \thepenaltyiii\relax% \advance\qr@a by \thepenaltyiv\relax% \edef\qr@penalty{\the\qr@a}% }% \def\qr@removefirsttoken#1{% %Removes the first token from the macro named in #1. \edef\qr@argument{(#1)}% \xa\qr@removefirsttoken@int\qr@argument% \xdef#1{\qr@removefirsttoken@result}% }% \def\qr@removefirsttoken@int(#1#2){% \def\qr@removefirsttoken@result{#2}% }% \def\qr@writeformatstring#1#2{% % #1 = matrix name % #2 = binary string representing the encoded and masked format information \setcounter{qr@i}{9}% \setcounter{qr@j}{1}% \edef\qr@argument{{#1}(#2\relax)}% \xa\qr@writeformatA@recursive\qr@argument % \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% \setcounter{qr@j}{9}% \xa\qr@writeformatB@recursive\qr@argument }% \def\qr@writeformatA@recursive#1(#2#3){% % #1 = matrix name % #2 = first bit of string % #3 = rest of bitstream % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) \ifnum#2=1\relax \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% \else \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% \fi % Now the tricky part--moving \i and \j to their next positions. \ifnum\c@qr@j<9\relax %If we're not yet in column 9, move right. \stepcounter{qr@j}% \ifnum\c@qr@j=7\relax %But we skip column 7! \stepcounter{qr@j}% \fi \else %If we're in column 9, we move up. \addtocounter{qr@i}{-1}% \ifnum\c@qr@i=7\relax %But we skip row 7! \addtocounter{qr@i}{-1}% \fi \fi %N.B. that at the end of time, this will leave us at invalid position (0,9). %That makes for an easy test to know when we are done. \ifnum\c@qr@i<1 \let\qr@next=\relax \else \def\qr@next{\qr@writeformatA@recursive{#1}(#3)}% \fi \qr@next }% \def\qr@writeformatB@recursive#1(#2#3){% % #1 = matrix name % #2 = first bit of string % #3 = rest of bitstream % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) \ifnum#2=1\relax \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% \else \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% \fi % Now the tricky part--moving counters i and j to their next positions. \qr@a=\qr@size% \advance\qr@a by -6\relax% \ifnum\qr@a<\c@qr@i\relax %If we're not yet in row n-6, move up. \addtocounter{qr@i}{-1}% \else \ifnum\qr@a=\c@qr@i\relax %If we're actually in row n-6, we jump to position (9,n-7). \setcounter{qr@i}{9}% %Set counter j equal to \qr@size-7. \global\c@qr@j=\qr@size\relax% \global\advance\c@qr@j by -7\relax% \else %Otherwise, we must be in row 9. %In this case, we move right. \stepcounter{qr@j}% \fi \fi %N.B. that at the end of time, this will leave us at invalid position (9,n+1). %That makes for an easy test to know when we are done. \xa\ifnum\qr@size<\c@qr@j\relax \let\qr@next=\relax \else \def\qr@next{\qr@writeformatB@recursive{#1}(#3)}% \fi \qr@next }% \def\qr@writeversionstring#1#2{% % #1 = matrix name % #2 = binary string representing the encoded version information % % Plot the encoded version string into the matrix. % This is only done for versions 7 and higher. \xa\ifnum\qr@version>6\relax %Move to position (n-8,6). \setcounter{qr@i}{\qr@size}\relax% \addtocounter{qr@i}{-8}\relax% \setcounter{qr@j}{6}% \edef\qr@argument{{#1}(#2\relax)}% \xa\qr@writeversion@recursive\qr@argument \fi }% \def\qr@writeversion@recursive#1(#2#3){% % #1 = matrix name % #2 = first bit of string % #3 = rest of bitstream % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) % % The version information is stored symmetrically in the matrix % In two transposed regions, so we can write both at the same time. % In the comments, we describe what happens in the lower-left region, % not the upper-right. % %Set \qr@topline equal to n-10. \qr@a=\qr@size\relax% \advance\qr@a by -10\relax% \edef\qr@topline{\the\qr@a}% % \ifnum#2=1\relax \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@black@format}% \else \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@white@format}% \fi % Now the tricky part--moving counters i and j to their next positions. \addtocounter{qr@i}{-1}% \xa\ifnum\qr@topline>\c@qr@i\relax %We've overshot the top of the region. %We need to move left one column and down three. \addtocounter{qr@j}{-1}% \addtocounter{qr@i}{3}% \fi %N.B. that at the end of time, this will leave us at invalid position (n-8,0). %That makes for an easy test to know when we are done. \ifnum\c@qr@j<1\relax \let\qr@next=\relax \else \def\qr@next{\qr@writeversion@recursive{#1}(#3)}% \fi \qr@next }% % \end{macrocode} % % \subsection{Encoding and error correction} % \begin{macrocode} \newcounter{qr@hexchars}% \def\qr@string@binarytohex#1{% \qr@binarytohex{\qr@hex@result}{#1}% }% \def\qr@encode@binary#1{% % #1 = string of ascii characters, to be converted into bitstream % % We do this one entirely in hex, rather than binary, because we can. \edef\qr@plaintext{#1}% % %First, the mode indicator. \def\qr@codetext{4}% %This means `binary' % %Next, the character count. \qr@getstringlength{\qr@plaintext}% %Set \qr@charactercountlengthinhex to \qr@charactercountbits@byte/4% \qr@a=\qr@charactercountbits@byte\relax% \divide \qr@a by 4\relax% \edef\qr@charactercountlengthinhex{\the\qr@a}% \qr@decimaltohex[\qr@charactercountlengthinhex]{\qr@charactercount}{\qr@stringlength}% \xa\g@addto@macro\xa\qr@codetext\xa{\qr@charactercount}% % %Now comes the actual data. \edef\qr@argument{(,\qr@plaintext\relax\relax\relax)}% \xa\qr@encode@ascii@recursive\qr@argument% % %Now the terminator. \g@addto@macro\qr@codetext{0}% %This is '0000' in binary. % %There is no need to pad bits to make a multiple of 8, %because the data length is already 4 + 8 + 8n + 4. % %Now add padding codewords if needed. \setcounter{qr@hexchars}{0}% \qr@getstringlength{\qr@codetext}% \setcounter{qr@hexchars}{\qr@stringlength}% %Set \qr@numpaddingcodewords equal to \qr@totaldatacodewords - qr@hexchars/2. \qr@a=-\c@qr@hexchars\relax \divide\qr@a by 2\relax \advance\qr@a by \qr@totaldatacodewords\relax \edef\qr@numpaddingcodewords{\the\qr@a}% % \xa\ifnum\qr@numpaddingcodewords<0% \edef\ds{ERROR: Too much data! Over by \qr@numpaddingcodewords bytes.}\show\ds% \fi% \xa\ifnum\qr@numpaddingcodewords>0% \qr@for \i = 2 to \qr@numpaddingcodewords by 2% {\g@addto@macro{\qr@codetext}{ec11}}% \xa\ifodd\qr@numpaddingcodewords\relax% \g@addto@macro{\qr@codetext}{ec}% \fi% \fi% }% \def\qr@encode@ascii@recursive(#1,#2#3){% % #1 = hex codes translated so far % #2 = next plaintext character to translate % #3 = remainder of plaintext \edef\qr@testii{#2}% \ifx\qr@testii\qr@relax% % All done! \g@addto@macro\qr@codetext{#1}% \else% % Another character to translate. \edef\qr@asciicode{\number`#2}% \qr@decimaltohex[2]{\qr@newhexcodes}{\qr@asciicode}% \edef\qr@argument{(#1\qr@newhexcodes,#3)}% %\show\qr@argument \xa\qr@encode@ascii@recursive\qr@argument% \fi% }% \def\qr@splitcodetextintoblocks{% \setcounter{qr@i}{0}% \qr@for \j = 1 to \qr@numshortblocks by 1% {\stepcounter{qr@i}% \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@shortblock@size}% }% \xa\ifnum\qr@numlongblocks>0\relax% \qr@for \j = 1 to \qr@numlongblocks by 1% {\stepcounter{qr@i}% \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@longblock@size}% }% \fi% }% \def\qr@splitoffblock#1#2#3{% % #1 = current codetext in hexadecimal % #2 = number to use in csname "\datablock@#2". % #3 = number of bytes to split off \message{}% \xa\gdef\csname datablock@#2\endcsname{}% %This line is important! \qr@for \i = 1 to #3 by 1% {\edef\qr@argument{{#2}(#1)}% \xa\qr@splitoffblock@int\qr@argument% }% }% \def\qr@splitoffblock@int#1(#2#3#4){% % #1 = number to use in csname "\datablock@#1". % #2#3 = next byte to split off % #4 = remaining text % % We add the next byte to "\datablock@#1", % and we remove it from the codetext. \xa\xdef\csname datablock@#1\endcsname{\csname datablock@#1\endcsname#2#3}% \xdef\qr@codetext{#4}% }% \def\qr@createerrorblocks{% \qr@for \ii = 1 to \qr@numblocks by 1% {\message{}% \FX@generate@errorbytes{\csname datablock@\the\ii\endcsname}{\qr@num@eccodewords}% \xa\xdef\csname errorblock@\the\ii\endcsname{\FX@errorbytes}% }% }% \def\qr@interleave{% \setcounter{qr@i}{0}% \def\qr@interleaved@text{}% \message{0\relax% \message{\qr@longblock@size.>}% \else \message{.>}% \fi \message{}% }% \def\qr@writefromblock#1#2{% % #1 = either 'datablock' or 'errorblock' % #2 = block number, in {1,...,\qr@numblocks}% \edef\qr@argument{(\csname #1@#2\endcsname\relax\relax\relax)}% \xa\qr@writefromblock@int\qr@argument \xa\xdef\csname #1@#2\endcsname{\qr@writefromblock@remainder}% }% \def\qr@writefromblock@int(#1#2#3){% % #1#2 = first byte (in hex) of text, which will be written to \qr@interleaved@text % #3 = remainder, including \relax\relax\relax terminator. \g@addto@macro{\qr@interleaved@text}{#1#2}% \qr@writefromblock@intint(#3)% }% \def\qr@writefromblock@intint(#1\relax\relax\relax){% \xdef\qr@writefromblock@remainder{#1}% }% % \end{macrocode} % % \subsection{Encoding format and version information} % \begin{macrocode} \let\xa=\expandafter \makeatletter \def\qr@preface@macro#1#2{% % #1 = macro name % #2 = text to add to front of macro \def\qr@tempb{#2}% \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% }% \newif\ifqr@leadingcoeff \def\qr@testleadingcoeff(#1#2){% % Tests whether the leading digit of #1#2 is 1. \ifnum#1=1\relax \qr@leadingcoefftrue \else \qr@leadingcoefffalse \fi }% \def\qr@polynomialdivide#1#2{% \edef\qr@numerator{#1}% \edef\qr@denominator{#2}% \qr@divisiondonefalse% \xa\xa\xa\qr@oneroundofdivision\xa\xa\xa{\xa\qr@numerator\xa}\xa{\qr@denominator}% }% \def\@qr@empty{}% \def\qr@oneroundofdivision#1#2{% % #1 = f(x), of degree n % #2 = g(x), of degree m % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), % but of degree at most n-1. % % If leading coefficient of f(x) is 1, subtracts off g(x) * x^(n-m). % If leading coefficient of f(x) is 0, strips off that leading zero. % \qr@testleadingcoeff(#1)% \ifqr@leadingcoeff \qr@xorbitstrings{#1}{#2}% \ifqr@xorfailed %If xor failed, that means our #1 was already the remainder! \qr@divisiondonetrue \edef\qr@theremainder{#1}% \else %xor succeeded. We need to recurse. \xa\xa\xa\edef\xa\xa\xa\qr@numerator\xa\xa\xa{\xa\qr@stripleadingzero\xa(\qr@xorresult)}% \fi \else \xa\def\xa\qr@numerator\xa{\qr@stripleadingzero(#1)}% \ifx\qr@numerator\@qr@empty \qr@divisiondonetrue \def\qr@theremainder{0}% \fi \fi \ifqr@divisiondone \relax \else \xa\qr@oneroundofdivision\xa{\qr@numerator}{#2}% \fi }% \def\qr@stripleadingzero(0#1){#1}%Strips off a leading zero. \newif\ifqr@xorfailed% This flag will trigger when #2 is longer than #1. \def\qr@xorbitstrings#1#2{% % #1 = bitstring % #2 = bitstring no longer than #1 \qr@xorfailedfalse \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% \xa\qr@xorbitstrings@recursive\qr@argument %\qr@xorbitstrings@recursive(,#1\relax\relax)(#2\relax\relax)% }% \def\qr@xorbitstrings@recursive(#1,#2#3)(#4#5){% % #1#2#3 is the first bitstring, xor'ed up through #1. % #4#5 is the remaining portion of the second bitstring. \def\qr@testii{#2}% \def\qr@testiv{#4}% \ifx\qr@testii\qr@relax % #1 contains the whole string. % Now if #4 is also \relax, that means the two strings started off with equal lengths. % If, however, #4 is not \relax, that means the second string was longer than the first, a problem. \ifx\qr@testiv\qr@relax %No problem. We are done. \qr@xorbit@saveresult(#1#2#3)% \else %Problem! The second string was longer than the first. \qr@xorfailedtrue \def\qr@xorresult{}% \fi \else % There is still a bit to manipulate in #2. % Check whether #4 contains anything. \ifx\qr@testiv\qr@relax % No, #4 is empty. We are done. "#2#3" contains the remainder of the first string, % which we append untouched and then strip off the two \relax-es. \qr@xorbit@saveresult(#1#2#3)% \else % Yes, #4 still has something to XOR. Do the task. \ifnum#2=#4\relax \qr@xorbitstrings@recursive(#1% 0,#3)(#5)% \else \qr@xorbitstrings@recursive(#1% 1,#3)(#5)% \fi \fi \fi }% \def\qr@xorbit@saveresult(#1\relax\relax){% %Strips off the extra '\relax'es at the end. \def\qr@xorresult{#1}% }% \newif\ifqr@divisiondone \def\qr@BCHcode#1{% \edef\qr@formatinfo{#1}% \def\qr@formatinfopadded{\qr@formatinfo 0000000000}% \def\qr@divisor{10100110111}% \qr@divisiondonefalse \qr@polynomialdivide{\qr@formatinfopadded}{\qr@divisor}% % \qr@getstringlength{\qr@theremainder}% %Run loop from stringlength+1 to 10. \qr@a=\qr@stringlength\relax% \advance\qr@a by 1\relax% \qr@for \i = \qr@a to 10 by 1% {\qr@preface@macro{\qr@theremainder}{0}% \xdef\qr@theremainder{\qr@theremainder}% }% \edef\qr@BCHresult{\qr@formatinfo\qr@theremainder}% }% \def\qr@formatmask{101010000010010}% \def\qr@encodeandmaskformat#1{% \qr@BCHcode{#1}% \qr@xorbitstrings{\qr@BCHresult}{\qr@formatmask}% \edef\qr@format@bitstring{\qr@xorresult}% }% \def\qr@Golaycode#1{% % #1 = 6-bit version number \edef\qr@versioninfo{#1}% \def\qr@versioninfopadded{\qr@versioninfo 000000000000}% %Append 12 zeros. \def\qr@divisor{1111100100101}% \qr@divisiondonefalse \qr@polynomialdivide{\qr@versioninfopadded}{\qr@divisor}% % \qr@getstringlength{\qr@theremainder}% %Run loop from stringlength+1 to 12. \qr@a=\qr@stringlength\relax% \advance\qr@a by 1\relax% \qr@for \i = \qr@a to 12 by 1% {\qr@preface@macro{\qr@theremainder}{0}% \xdef\qr@theremainder{\qr@theremainder}% }% \edef\qr@Golayresult{\qr@versioninfo\qr@theremainder}% }% % \end{macrocode} % % \subsection{Error correction} % The error-correction code is defined over $\F_{256}=GF(256)$, % the finite field of order $256$. % The QR specification encodes this field as $\F_2[X]/(X^8+X^4+X^3+X^2+1)$; % in other words, each field element is an 8-bit binary string representing % an integer between 0 and 255. % % We represent these 8-bit strings as two hexadecimal characters; % for example, {\tt 5a} represents {\tt 01011010}. % Because addition is done by xor-ing the bitstrings, % we can define addition on hexadecimal characters. % Since there are only $16^2$ possibilities, % we create a lookup table. % \begin{macrocode} \def\F@result{}% \def\qr@xorbitstring#1#2#3{% % #1 = new macro to receive result % #2, #3 = bitstrings to xor. The second can be shorter than the first. \def\qr@xor@result{}% \edef\qr@argument{(#2\relax\relax)(#3\relax\relax)}% \xa\qr@xorbitstring@recursive\qr@argument% \edef#1{\qr@xor@result}% }% \def\qr@xorbitstring@recursive(#1#2)(#3#4){% \edef\qr@testi{#1}% \ifx\qr@testi\qr@relax% %Done. \let\qr@next=\relax% \else \if#1#3\relax \g@addto@macro{\qr@xor@result}{0}% \else \g@addto@macro{\qr@xor@result}{1}% \fi \edef\qr@next{\noexpand\qr@xorbitstring@recursive(#2)(#4)}% \fi \qr@next } \def\F@addchar@raw#1#2{% %Add two hexadecimal digits using bitwise xor \qr@hextobinary[4]{\qr@summandA}{#1}% \qr@hextobinary[4]{\qr@summandB}{#2}% \qr@xorbitstring{\F@result}{\qr@summandA}{\qr@summandB}% \qr@binarytohex[1]{\F@result}{\F@result}% }% \def\qr@canceltwos#1{% \edef\qr@argument{(#1\relax\relax)}% \xa\qr@canceltwos@int\qr@argument% }% \def\qr@canceltwos@int(#1#2){% \xa\qr@canceltwos@recursion(,#1#2)% }% \def\qr@canceltwos@recursion(#1,#2#3){% \def\qr@testii{#2}% \ifx\qr@testii\qr@relax %Cancelling complete. \qr@striptworelaxes(#1#2#3)% %Now \F@result contains the answer. \else \relax \ifnum#2=2\relax \qr@canceltwos@recursion(#10,#3)% \else \qr@canceltwos@recursion(#1#2,#3)% \fi \fi }% \def\qr@striptworelaxes(#1\relax\relax){% \gdef\F@result{#1}% }% \qr@for \i = 0 to 15 by 1% {\qr@decimaltohex[1]{\qr@tempa}{\the\i}% \qr@for \j = 0 to 15 by 1% {\qr@decimaltohex[1]{\qr@tempb}{\the\j}% \F@addchar@raw\qr@tempa\qr@tempb \xa\xdef\csname F@addchar@\qr@tempa\qr@tempb\endcsname{\F@result}% }% }% \def\F@addchar#1#2{% \xa\def\xa\F@result\xa{\csname F@addchar@#1#2\endcsname}% }% \def\F@addstrings#1#2{% \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% \xa\F@addstrings@recursion\qr@argument% }% \def\F@addstrings@recursion(#1,#2#3)(#4#5){% %Adds two hexadecimal strings, bitwise, from left to right. %The second string is allowed to be shorter than the first. \def\qr@testii{#2}% \def\qr@testiv{#4}% \ifx\qr@testii\qr@relax %The entire string has been processed. \gdef\F@result{#1}% \else \ifx\qr@testiv\qr@relax %The second string is over. \qr@striptworelaxes(#1#2#3)% %Now \F@result contains the answer. \else %We continue to add. \F@addchar{#2}{#4}% \edef\qr@argument{(#1\F@result,#3)(#5)}% \xa\F@addstrings@recursion\qr@argument% \fi \fi }% % \end{macrocode} % Now we handle multiplication. % Our approach to multiplying $a,b\in\F_{256}$ % is to take discrete logarithms (with 2 as our base), % add the logarithms, and then take the antilog. % We first create a log table. % \begin{macrocode} \gdef\F@stripleadingzero(0#1){\edef\F@result{#1}}% \setcounter{qr@i}{0}% \def\qr@poweroftwo{1}% \qr@for \i = 1 to 254 by 1% {\stepcounter{qr@i}% \qr@a=\qr@poweroftwo\relax \multiply\qr@a by 2\relax \edef\qr@poweroftwo{\the\qr@a}% %\show\qr@poweroftwo \qr@decimaltohex[2]{\qr@poweroftwo@hex}{\qr@poweroftwo}% \xa\ifnum\qr@poweroftwo>255\relax %We need to bitwise add the polynomial represented by 100011101, i.e. 0x11d. \F@addstrings{\qr@poweroftwo@hex}{11d}% %Now it should start with 0. \xa\F@stripleadingzero\xa(\F@result)% %Now it should be two hex digits. \edef\qr@poweroftwo@hex{\F@result}% %Save the hex version. \qr@hextodecimal{\qr@poweroftwo}{\F@result}% \fi \xdef\qr@poweroftwo{\qr@poweroftwo}% \xa\xdef\csname F@twotothe@\theqr@i\endcsname{\qr@poweroftwo@hex}% \xa\xdef\csname F@logtwo@\qr@poweroftwo@hex\endcsname{\theqr@i}% }% \xa\xdef\csname F@twotothe@0\endcsname{01}% \xa\xdef\csname F@logtwo@01\endcsname{0}% \def\F@twotothe#1{% \xa\xdef\xa\F@result\xa{\csname F@twotothe@#1\endcsname}% }% \def\F@logtwo#1{% \xa\xdef\xa\F@result\xa{\csname F@logtwo@#1\endcsname}% }% \def\qr@zerozero{00}% \def\F@multiply#1#2{% % #1 and #2 are two elements of F_256, % given as two-character hexadecimal strings. % Multiply them within F_256, and place the answer in \F@result \edef\qr@argA{#1}% \edef\qr@argB{#2}% \ifx\qr@argA\qr@zerozero \def\F@result{00}% \else \ifx\qr@argB\qr@zerozero \def\F@result{00}% \else \xa\F@logtwo\xa{\qr@argA}% \edef\qr@logA{\F@result}% \xa\F@logtwo\xa{\qr@argB}% \edef\qr@logB{\F@result}% \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB \ifnum\qr@a>254\relax% \advance\qr@a by -255\relax% \fi% \xa\F@twotothe\xa{\the\qr@a}% % Now \F@result contains the product, as desired. \fi \fi }% \def\F@multiply#1#2{% % #1 and #2 are two elements of F_256, % given as two-character hexadecimal strings. % Multiply them within F_256, and place the answer in \F@result \edef\qr@argA{#1}% \edef\qr@argB{#2}% \ifx\qr@argA\qr@zerozero \def\F@result{00}% \else \ifx\qr@argB\qr@zerozero \def\F@result{00}% \else \xa\F@logtwo\xa{\qr@argA}% \edef\qr@logA{\F@result}% \xa\F@logtwo\xa{\qr@argB}% \edef\qr@logB{\F@result}% \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB \ifnum\qr@a>254\relax% \advance\qr@a by -255\relax% \fi% \xa\F@twotothe\xa{\the\qr@a}% % Now \F@result contains the product, as desired. \fi \fi }% % \end{macrocode} % Having developed $\F_{256}$, we now turn to the real task. % Each byte of data is read as an element of $\F_{256}$, % and a sequence of bytes corresponds a polynomial in % $\F_{256}[X]$. % The Reed-Solomon code takes that codeword $f(X)\in \F_{256}[X]$ % of degree $k$, divides $f(X)\cdot X^\ell$ by a fixed % polynomial, % and keeps the remainder $r(X)$ as the error-correction word. % We therefore must implement polynomial division over $\F_{256}$. % \begin{macrocode} %These polynomials are represented as sequences of coefficients, %from highest power to lowest, %with each coefficient represented by two hexadecimal characters. \def\FX@getstringlength#1{% %Count number of two-character coefficients \setcounter{qr@i}{0}% \xdef\qr@argument{(#1\relax\relax\relax)}% \xa\FX@stringlength@recursive\qr@argument% \xdef\stringresult{\arabic{qr@i}}% }% \def\FX@stringlength@recursive(#1#2#3){% \def\qr@testi{#1}% \ifx\qr@testi\qr@relax %we are done. \else \stepcounter{qr@i}% %\showthe\c@qr@i \qr@stringlength@recursive(#3)% \fi }% \newif\ifFX@leadingcoeff@zero \def\FX@testleadingcoeff(#1#2#3){% % Tests whether the leading coefficient of the hex-string #1#2#3 is '00'. \edef\FX@leadingcoefficient{#1#2}% \FX@leadingcoeff@zerofalse \ifx\FX@leadingcoefficient\qr@zerozero \FX@leadingcoeff@zerotrue \fi }% \newif\ifFX@divisiondone \newcounter{qr@divisionsremaining} %Keep track of how many divisions to go! \def\FX@polynomialdivide#1#2{% \edef\FX@numerator{#1}% \edef\FX@denominator{#2}% \qr@getstringlength\FX@numerator% \setcounter{qr@divisionsremaining}{\qr@stringlength}% \qr@getstringlength\FX@denominator% \addtocounter{qr@divisionsremaining}{-\qr@stringlength}% \addtocounter{qr@divisionsremaining}{2}% \divide\c@qr@divisionsremaining by 2\relax% %2 hex chars per number \FX@divisiondonefalse% \xa\xa\xa\FX@polynomialdivide@recursive\xa\xa\xa{\xa\FX@numerator\xa}\xa{\FX@denominator}% }% \def\FX@polynomialdivide@recursive#1#2{% % #1 = f(x), of degree n % #2 = g(x), of degree m % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), % but of degree at most n-1. % % If leading coefficient of f(x) is 0, strips off that leading zero. % If leading coefficient of f(x) is a, subtracts off a * g(x) * x^(n-m). % N.B. we assume g is monic. % \FX@testleadingcoeff(#1)% \ifFX@leadingcoeff@zero% %Leading coefficient is zero, so remove it. \xa\def\xa\FX@numerator\xa{\FX@stripleadingzero(#1)}% \else% %Leading coefficient is nonzero, and contained in \FX@leadingcoefficient \FX@subtractphase{#1}{#2}{\FX@leadingcoefficient}% \ifFX@subtract@failed% %If subtraction failed, that means our #1 was already the remainder! \FX@divisiondonetrue% \edef\qr@theremainder{#1}% \else% %xor succeeded. We need to recurse. \xa\xa\xa\edef\xa\xa\xa\FX@numerator\xa\xa\xa{\xa\FX@stripleadingzero\xa(\FX@subtraction@result)}% \fi% \fi% \addtocounter{qr@divisionsremaining}{-1}% \ifnum\c@qr@divisionsremaining=0\relax %Division is done! \FX@divisiondonetrue% \edef\qr@theremainder{\FX@numerator}% \relax% \else% \xa\FX@polynomialdivide@recursive\xa{\FX@numerator}{#2}% \fi% }% \def\FX@stripleadingzero(00#1){#1}%Strips off a single leading zero of F_256. \newif\ifFX@subtract@failed% This flag will trigger when #2 is longer than #1. \def\FX@subtractphase#1#2#3{% % #1 = bitstring % #2 = bitstring no longer than #1 % #3 = leading coefficient \FX@subtract@failedfalse% \edef\qr@argument{(,#1\relax\relax\relax)(#2\relax\relax\relax)(#3)}% \xa\FX@subtract@recursive\qr@argument% }% \def\FX@subtract@recursive(#1,#2#3#4)(#5#6#7)(#8){% % This is a recursive way to compute f(x) - a*g(x)*x^k. % #1#2#3#4 is the first bitstring, subtracted up through #1. % Thus #2#3 constitutes the next two-character coefficient. % #5#6#7 is the remaining portion of the second bitstring. % Thus #5#6 constitutes the next two-character coefficient % #8 is the element a of F_256. It should contain two characters. \def\qr@testii{#2}% \def\qr@testv{#5}% \ifx\qr@testii\qr@relax % #1 contains the whole string. % Now if #5 is also \relax, that means the two strings started off with equal lengths. % If, however, #5 is not \relax, that means the second string was longer than the first, a problem. \ifx\qr@testv\qr@relax %No problem. We are done. \FX@subtract@saveresult(#1#2#3#4)% %We keep the #2#3#4 to be sure we have all three relax-es to strip off. \else %Problem! The second string was longer than the first. %This usually indicates the end of the long division process. \FX@subtract@failedtrue \def\FX@subtraction@result{}% \fi \else % There is still a coefficient to manipulate in #2#3. % Check whether #5 contains anything. \ifx\qr@testv\qr@relax % No, #5 is empty. We are done. "#2#3#4" contains the remainder of the first string, % which we append untouched and then strip off the three \relax-es. \FX@subtract@saveresult(#1#2#3#4)% \else % Yes, #5#6 still has something to XOR. Do the task. \F@multiply{#5#6}{#8}% Multiply by the factor 'a'. \F@addstrings{#2#3}{\F@result}% Subtract. (We're in characteristic two, so adding works.) \edef\qr@argument{(#1\F@result,#4)(#7)(#8)}% \xa\FX@subtract@recursive\qr@argument% \fi \fi }% \def\FX@subtract@saveresult(#1\relax\relax\relax){% %Strips off the three extra '\relax'es at the end. \def\FX@subtraction@result{#1}% }% \def\FX@creategeneratorpolynomial#1{% % #1 = n, the number of error codewords desired. % We need to create \prod_{j=0}^{n-1} (x-2^j). \edef\FX@generator@degree{#1}% \def\FX@generatorpolynomial{01}% Initially, set it equal to 1. \setcounter{qr@i}{0}% \FX@creategenerator@recursive% %The result is now stored in \FX@generatorpolynomial }% \def\FX@creategenerator@recursive{% % \c@qr@i contains the current value of i. % \FX@generatorpolynomial contains the current polynomial f(x), % which should be a degree-i polynomial % equal to \prod_{j=0}^{i-1} (x-2^j). % (If i=0, then \FX@generatorpolynomial should be 01.) % This recursion step should multiply the existing polynomial by (x-2^i), % increment i by 1, and check whether we're done or not. \edef\qr@summandA{\FX@generatorpolynomial 00}% This is f(x) * x \edef\qr@summandB{00\FX@generatorpolynomial}% This is f(x), with a 0x^{i+1} in front. \F@twotothe{\theqr@i}% \edef\qr@theconstant{\F@result}% \FX@subtractphase{\qr@summandA}{\qr@summandB}{\qr@theconstant}% %This calculates \qr@summandA + \qr@theconstant * \qr@summandB %and stores the result in \FX@subtraction@result \edef\FX@generatorpolynomial{\FX@subtraction@result}% \stepcounter{qr@i}% \xa\ifnum\FX@generator@degree=\c@qr@i\relax% %We just multiplied by (x-2^{n-1}), so we're done. \relax% \else% %We need to do this again! \xa% \FX@creategenerator@recursive% \fi% }% \def\FX@generate@errorbytes#1#2{% % #1 = datastream in hex % #2 = number of error correction bytes requested \edef\qr@numerrorbytes{#2}% \xa\FX@creategeneratorpolynomial\xa{\qr@numerrorbytes}% \edef\FX@numerator{#1}% \qr@for \i = 1 to \qr@numerrorbytes by 1% {\g@addto@macro\FX@numerator{00}}% %One error byte means two hex codes. \FX@polynomialdivide{\FX@numerator}{\FX@generatorpolynomial}% \edef\FX@errorbytes{\qr@theremainder}% }% % \end{macrocode} % % \subsection{Version handling} % \begin{macrocode} \newif\ifqr@versionmodules \def\qr@level@char#1{% \xa\ifcase#1 M\or L\or H\or Q\fi}% \newif\ifqr@versiongoodenough \def\qr@choose@best@version#1{% % \qr@desiredversion = user-requested version % \qr@desiredlevel = user-requested error-correction level \edef\qr@plaintext{#1}% \qr@getstringlength{\qr@plaintext}% % %Run double loop over levels and versions, looking for %the smallest version that can contain our data, %and then choosing the best error-correcting level at that version, %subject to the level being at least as good as the user desires. \global\qr@versiongoodenoughfalse% \gdef\qr@bestversion{0}% \gdef\qr@bestlevel{0}% \ifnum\qr@desiredversion=0\relax \qr@a=1\relax \else \qr@a=\qr@desiredversion\relax \fi \qr@for \i=\qr@a to 40 by 1 {\edef\qr@version{\the\i}% \global\qr@versiongoodenoughfalse \qr@for \j=0 to 3 by 1% {%First, we map {0,1,2,3} to {1,0,4,3}, so that we loop through {M,L,H,Q} %in order of increasing error-correction capabilities. \qr@a = \j\relax \divide \qr@a by 2\relax \multiply \qr@a by 4\relax \advance \qr@a by 1\relax \advance \qr@a by -\j\relax \edef\qr@level{\the\qr@a}% \ifnum\qr@desiredlevel=\qr@a\relax \global\qr@versiongoodenoughtrue \fi \ifqr@versiongoodenough \qr@calculate@capacity{\qr@version}{\qr@level}% \xa\xa\xa\ifnum\xa\qr@truecapacity\xa<\qr@stringlength\relax %Too short \relax \else %Long enough! \xdef\qr@bestversion{\qr@version}% \xdef\qr@bestlevel{\qr@level}% \global\i=40% \fi \fi }% }% \edef\qr@version{\qr@bestversion}% \edef\qr@level{\qr@bestlevel}% \xa\ifnum\qr@desiredversion>0\relax \ifx\qr@bestversion\qr@desiredversion\relax %No change from desired version. \else %Version was increased \message{^^J}% \fi \fi \ifx\qr@bestlevel\qr@desiredlevel\relax %No change in level. \else \message{^^J}% \fi }% \def\qr@calculate@capacity#1#2{% \edef\qr@version{#1}% \edef\qr@level{#2}% %Calculate \qr@size, the number of modules per side. % The formula is 4\qr@version+17. \qr@a=\qr@version\relax% \multiply\qr@a by 4\relax% \advance\qr@a by 17\relax% \edef\qr@size{\the\qr@a}% % % Calculate \qr@k, which governs the number of alignment patterns. % The alignment patterns lie in a kxk square, except for 3 that are replaced by finding patterns. % The formula is 2 + floor( \qr@version / 7 ), except that k=0 for version 1. \xa\ifnum\qr@version=1\relax% \def\qr@k{0}% \else% \qr@a=\qr@version\relax \divide \qr@a by 7\relax \advance\qr@a by 2\relax \edef\qr@k{\the\qr@a}% \fi% % %Calculate number of function pattern modules. %This consists of the three 8x8 finder patterns, the two timing strips, and the (k^2-3) 5x5 alignment patterns. %The formula is 160+2n+25(k^2-3)-10(k-2), unless k=0 in which case we just have 160+2n. \qr@a=\qr@size\relax \multiply\qr@a by 2\relax \advance\qr@a by 160\relax \xa\ifnum\qr@k=0\relax\else %\qr@k is nonzero, hence at least 2, so we continue to add 25(k^2-3)-10(k-2). \qr@b=\qr@k\relax \multiply\qr@b by \qr@k\relax \advance\qr@b by -3\relax \multiply\qr@b by 25\relax \advance\qr@a by \qr@b\relax \qr@b=\qr@k\relax \advance\qr@b by -2\relax \multiply\qr@b by 10\relax \advance\qr@a by -\qr@b\relax \fi \edef\qr@numfunctionpatternmodules{\the\qr@a}% % %Calculate the number of version modules, either 36 or 0. \xa\ifnum\qr@version>6\relax \qr@versionmodulestrue \def\qr@numversionmodules{36}% \else \qr@versionmodulesfalse \def\qr@numversionmodules{0}% \fi % %Now calculate the codeword capacity and remainder bits. %Take n^2 modules, subtract all those dedicated to finder patterns etc., format information, and version information, %and what's left is the number of bits we can play with. %The number of complete bytes is \qr@numdatacodewords; %the leftover bits are \qr@numremainderbits. \qr@a=\qr@size\relax \multiply \qr@a by \qr@size\relax \advance \qr@a by -\qr@numfunctionpatternmodules\relax \advance \qr@a by -31\relax% % There are 31 format modules. \advance \qr@a by -\qr@numversionmodules\relax \qr@b=\qr@a\relax \divide \qr@a by 8\relax \edef\qr@numdatacodewords{\the\qr@a}% \multiply\qr@a by 8\relax \advance \qr@b by -\qr@a\relax \edef\qr@numremainderbits{\the\qr@b}% % %The size of the character count indicator also varies by version. %There are only two options, so hardcoding seems easier than expressing these functionally. \xa\ifnum\qr@version<10\relax \def\qr@charactercountbytes@byte{1}% \def\qr@charactercountbits@byte{8}% \else \def\qr@charactercountbytes@byte{2}% \def\qr@charactercountbits@byte{16}% \fi % %Now we call on the table, from the QR specification, %of how many blocks to divide the message into, and how many error bytes each block gets. %This affects the true capacity for data, which we store into \qr@totaldatacodewords. % The following macro sets \qr@numblocks and \qr@num@eccodewords % based on Table 9 of the QR specification. \qr@settableix \qr@a = -\qr@numblocks\relax \multiply \qr@a by \qr@num@eccodewords\relax \advance\qr@a by \qr@numdatacodewords\relax \edef\qr@totaldatacodewords{\the\qr@a}% \advance\qr@a by -\qr@charactercountbytes@byte\relax%Subtract character count \advance\qr@a by -1\relax% Subtract 1 byte for the 4-bit mode indicator and the 4-bit terminator at the end. \edef\qr@truecapacity{\the\qr@a}% } \def\qr@setversion#1#2{% % #1 = version number, an integer between 1 and 40 inclusive. % #2 = error-correction level, as an integer between 0 and 3 inclusive. % 0 = 00 = M % 1 = 01 = L % 2 = 10 = H % 3 = 11 = Q % This macro calculates and sets a variety of global macros and/or counters % storing version information that is used later in construction the QR code. % Thus \qr@setversion should be called every time! % \edef\qr@version{#1}% \edef\qr@level{#2}% % \qr@calculate@capacity{\qr@version}{\qr@level}% %The capacity-check code sets the following: % * \qr@size % * \qr@k % * \ifqr@versionmodules % * \qr@numversionmodules % * \qr@numdatacodewords % * \qr@numremainderbits % * \qr@charactercountbits@byte % * \qr@charactercountbytes@byte % * \qr@numblocks (via \qr@settableix) % * \qr@num@eccodewords (via \qr@settableix) % * \qr@totaldatacodewords % % The alignment patterns' square is 7 modules in from each edge. % They are spaced "as evenly as possible" with an even number of modules between each row/column, % unevenness in division being accommodated by making the first such gap smaller. % The formula seems to be % general distance = 2*round((n-13)/(k-1)/2+0.25) % = 2*floor((n-13)/(k-1)/2+0.75) % = 2*floor( (2*(n-13)/(k-1)+3) / 4 ) % = (((2*(n-13)) div (k-1) + 3 ) div 4 ) * 2 % first distance = leftovers % The 0.25 is to accommodate version 32, which is the only time we round down. % Otherwise a simple 2*ceiling((n-13)/(k-1)/2) would have sufficed. % \qr@a = \qr@size\relax \advance\qr@a by -13\relax \multiply\qr@a by 2\relax \qr@b = \qr@k\relax \advance \qr@b by -1\relax \divide\qr@a by \qr@b\relax \advance\qr@a by 3\relax \divide\qr@a by 4\relax \multiply\qr@a by 2\relax \edef\qr@alignment@generalskip{\the\qr@a}% % %Now set \qr@alignment@firstskip to (\qr@size-13)-(\qr@k-2)*\qr@alignment@generalskip % \qr@a = \qr@k\relax \advance\qr@a by -2\relax \multiply\qr@a by -\qr@alignment@generalskip\relax \advance\qr@a by \qr@size\relax \advance\qr@a by -13\relax \edef\qr@alignment@firstskip{\the\qr@a}% % % % % Our \qr@totaldatacodewords bytes of data are broken up as evenly as possible % into \qr@numblocks datablocks; some may be one byte longer than others. % We set \qr@shortblock@size to floor(\qr@totaldatacodewords / \qr@numblocks) % and \qr@numlongblocks to mod(\qr@totaldatacodewords , \qr@numblocks). \qr@a=\qr@totaldatacodewords\relax \divide\qr@a by \qr@numblocks\relax \edef\qr@shortblock@size{\the\qr@a}% \multiply\qr@a by -\qr@numblocks\relax \advance\qr@a by \qr@totaldatacodewords\relax \edef\qr@numlongblocks{\the\qr@a}% % %Set \qr@longblock@size to \qr@shortblock@size+1. \qr@a=\qr@shortblock@size\relax \advance\qr@a by 1\relax \edef\qr@longblock@size{\the\qr@a}% % %Set \qr@numshortblocks to \qr@numblocks - \qr@numlongblocks \qr@b=\qr@numblocks\relax \advance\qr@b by -\qr@numlongblocks\relax \edef\qr@numshortblocks{\the\qr@b}% }% \def\qr@settableix@int(#1,#2){% \edef\qr@numblocks{#1}% \edef\qr@num@eccodewords{#2}% }% \def\qr@settableix{% \xa\ifcase\qr@level\relax %00: Level 'M', medium error correction \edef\qr@tempdata{(% \ifcase\qr@version\relax \relax %There is no version 0. \or1,10% \or1,16% \or1,26% \or2,18% \or2,24% \or4,16% \or4,18% \or4,22% \or5,22% \or5,26% \or5,30% \or8,22% \or9,22% \or9,24% \or10,24% \or10,28% \or11,28% \or13,26% \or14,26% \or16,26% \or17,26% \or17,28% \or18,28% \or20,28% \or21,28% \or23,28% \or25,28% \or26,28% \or28,28% \or29,28% \or31,28% \or33,28% \or35,28% \or37,28% \or38,28% \or40,28% \or43,28% \or45,28% \or47,28% \or49,28% \fi)}% \or %01: Level 'L', low error correction \edef\qr@tempdata{% (\ifcase\qr@version\relax \relax %There is no version 0. \or 1,7% \or 1,10% \or 1,15% \or 1,20% \or 1,26% \or 2,18% \or 2,20% \or 2,24% \or 2,30% \or 4,18% \or 4,20% \or 4,24% \or 4,26% \or 4,30% \or 6,22% \or 6,24% \or 6,28% \or 6,30% \or 7,28% \or 8,28% \or 8,28% \or 9,28% \or 9,30% \or 10,30% \or 12,26% \or 12,28% \or 12,30% \or 13,30% \or 14,30% \or 15,30% \or 16,30% \or 17,30% \or 18,30% \or 19,30% \or 19,30% \or 20,30% \or 21,30% \or 22,30% \or 24,30% \or 25,30% \fi)}% \or %10: Level 'H', high error correction \edef\qr@tempdata{(% \ifcase\qr@version\relax \relax %There is no version 0. \or1,17% \or1,28% \or2,22% \or4,16% \or4,22% \or4,28% \or5,26% \or6,26% \or8,24% \or8,28% \or11,24% \or11,28% \or16,22% \or16,24% \or18,24% \or16,30% \or19,28% \or21,28% \or25,26% \or25,28% \or25,30% \or34,24% \or30,30% \or32,30% \or35,30% \or37,30% \or40,30% \or42,30% \or45,30% \or48,30% \or51,30% \or54,30% \or57,30% \or60,30% \or63,30% \or66,30% \or70,30% \or74,30% \or77,30% \or81,30% \fi)}% \or %11: Level 'Q', quality error correction \edef\qr@tempdata{(% \ifcase\qr@version\relax \relax %There is no version 0. \or1,13% \or1,22% \or2,18% \or2,26% \or4,18% \or4,24% \or6,18% \or6,22% \or8,20% \or8,24% \or8,28% \or10,26% \or12,24% \or16,20% \or12,30% \or17,24% \or16,28% \or18,28% \or21,26% \or20,30% \or23,28% \or23,30% \or25,30% \or27,30% \or29,30% \or34,28% \or34,30% \or35,30% \or38,30% \or40,30% \or43,30% \or45,30% \or48,30% \or51,30% \or53,30% \or56,30% \or59,30% \or62,30% \or65,30% \or68,30% \fi)}% \fi \xa\qr@settableix@int\qr@tempdata }% % \end{macrocode} % \subsection{More key handling} % \begin{macrocode} \define@key{qr}{version}{\edef\qr@desiredversion{#1}}% \define@key{qr}{level}{\qr@setlevel{#1}}% \define@key{qr}{height}{\qr@setheight{#1}}% \define@boolkey{qr}[qr@]{tight}[true]{}% %This creates \ifqr@tight and initializes it to true. \define@boolkey{qr}[qr@]{padding}[true]{\ifqr@padding\qr@tightfalse\else\qr@tighttrue\fi}% %Define 'padding' as antonym to 'tight' \def\@qr@M{M}\def\@qr@z{0}% \def\@qr@L{L}\def\@qr@i{1}% \def\@qr@H{H}\def\@qr@ii{2}% \def\@qr@Q{Q}\def\@qr@iii{3}% \def\qr@setlevel#1{% \edef\qr@level@selected{#1}% \ifx\qr@level@selected\@qr@M \edef\qr@desiredlevel{0}% \fi \ifx\qr@level@selected\@qr@L \edef\qr@desiredlevel{1}% \fi \ifx\qr@level@selected\@qr@H \edef\qr@desiredlevel{2}% \fi \ifx\qr@level@selected\@qr@Q \edef\qr@desiredlevel{3}% \fi \ifx\qr@level@selected\@qr@z \edef\qr@desiredlevel{0}% \fi \ifx\qr@level@selected\@qr@i \edef\qr@desiredlevel{1}% \fi \ifx\qr@level@selected\@qr@ii \edef\qr@desiredlevel{2}% \fi \ifx\qr@level@selected\@qr@iii \edef\qr@desiredlevel{3}% \fi }% \def\qr@setheight#1{% \setlength{\qr@desiredheight}{#1}% }% \newcommand\qrset[1]{% \setkeys{qr}{#1}% } %SET DEFAULTS \qrset{version=0, level=0, tight} % \end{macrocode} % \subsection{Main user functions} % At last we are ready to define the main user functions. % Some care is needed to ensure % that the \meta{text to be encoded} is read with the appropriate catcodes, % and that any escaped special characters are converted to the intended % characters with category code 12 (other). % \begin{macrocode} \newif\ifqr@starinvoked% \def\qrcode{\@ifstar\qrcode@star\qrcode@nostar}% \def\qrcode@star{\qr@starinvokedtrue\qrcode@i}% \def\qrcode@nostar{\qr@starinvokedfalse\qrcode@i}% \newcommand\qrcode@i[1][]{% \begingroup% \ifqr@starinvoked% \qr@hyperlinkfalse% \fi% \setkeys{qr}{#1}% \bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qrcode@in}% \def\qrcode@in#1{\xdef\qr@texttoencode{#1}\egroup\qrcode@int\endgroup}% \def\qrcode@hyperwrapper@hyperref{\href{\qr@texttoencode}}% \def\qrcode@hyperwrapper@nohyperref{\relax}% \AtBeginDocument{% \@ifpackageloaded{hyperref}% {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@hyperref}% {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@nohyperref}% }% \def\qrcode@int{% \message{^^J^^J^^J}% %First, choose the version and level. %Recall that \qr@choose@best@version sets \qr@version and \qr@level. \xa\qr@choose@best@version\xa{\qr@texttoencode}% \qr@setversion{\qr@version}{\qr@level}% % \ifqr@hyperlink% \let\qrcode@wrapper=\qrcode@hyperwrapper% \else% \let\qrcode@wrapper=\relax% \fi% % %Next, check whether we have already encoded this text at this version %and level. \qrcode@wrapper{% \xa\ifx\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname \relax% %This text has not yet been encoded. \qrcode@int@new% \else %This text has already been encoded! \ifqr@forget@mode %In 'forget' mode, we deliberately recalculate anyway. \qrcode@int@new% \else \qrcode@int@remember% \fi \fi% }% }% \def\qrcode@int@new{% \qr@createsquareblankmatrix{newqr}{\qr@size}% \qr@placefinderpatterns{newqr}% \qr@placetimingpatterns{newqr}% \qr@placealignmentpatterns{newqr}% \qr@placedummyformatpatterns{newqr}% \qr@placedummyversionpatterns{newqr}% \ifqr@draft@mode \message{^^J}% \relax% Draft mode---don't load any data or do any work. Also don't save! \def\qr@format@square{\qr@black}% \def\qr@blank{\qr@white}% \fboxsep=-\fboxrule% \fbox{\qr@printmatrix{newqr}}% \else \message{^^J}% \xa\qr@encode@binary\xa{\qr@texttoencode}% \qr@splitcodetextintoblocks \qr@createerrorblocks \qr@interleave \message{^^J}% \qr@writeremainderbits{newqr}% \qr@chooseandapplybestmask{newqr}% \qr@decimaltobinary[2]{\qr@level@binary}{\qr@level}% \qr@decimaltobinary[3]{\qr@mask@binary}{\qr@mask@selected}% \edef\qr@formatstring{\qr@level@binary\qr@mask@binary}% \message{^^J}% \message{^^J}% \message{^^J}% % %Also save the binary version into the aux file, for use in later runs. \message{^^J}% \message{^^J}% \fi \message{^^J}% }% \def\qrcode@int@remember{% %This text has already been encoded, %so we just copy it from the saved binary string. \message{^^J}% \xa\qr@printsavedbinarymatrix\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% % % Now this still might need to be written to the aux file. % \xa\ifx\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname\@qr@TRUE %Okay, this has already been written to aux file. %Do nothing. \relax% \else% %This has NOT been written to the aux file yet. %We need to do so now. \xa\qr@writebinarymatrixtoauxfile\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% \fi% }% \def\qr@matrixtobinary#1{% \def\qr@binarymatrix@result{}% \bgroup \def\qr@black{1}% \def\qr@white{0}% \def\qr@blank{0}% \def\qr@black@fixed{1}% \def\qr@white@fixed{0}% \def\qr@black@format{1}% \def\qr@white@format{0}% % \qr@for \i = 1 to \qr@size by 1% {\qr@for \j = 1 to \qr@size by 1% {\edef\qr@theentry{\qr@matrixentry{#1}{\the\i}{\the\j}}% \xa\g@addto@macro\xa\qr@binarymatrix@result\xa{\qr@theentry}% }% }% \egroup% }% \def\qr@sanitize@output#1{% %Read through ASCII text '#1' and escape backslashes and braces \def\qr@sanitized@result{}% \edef\qr@argument{(#1\relax\relax\relax)}% \xa\qr@sanitize@output@int\qr@argument% } \def\qr@sanitize@output@int(#1#2){% % #1 = first character % #2 = rest of output, including terminator \edef\qr@testi{#1}% \ifx\qr@testi\qr@relax % Done. \let\qr@next=\relax \else \ifx\qr@testi\qr@otherrightbrace \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% \else\ifx\qr@testi\qr@otherleftbrace \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% \else\ifx\qr@testi\qr@otherbackslash \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% \fi \fi \fi \edef\qr@sanitized@result{\qr@sanitized@result#1}% \def\qr@next{\qr@sanitize@output@int(#2)}% \fi \qr@next } \def\@qr@TRUE{TRUE}% \def\qr@writebinarymatrixtoauxfile#1{% \qr@sanitize@output{\qr@texttoencode}% \edef\qr@theargument{{\qr@sanitized@result}{\qr@version}{\qr@level}{#1}}% \xa\write\xa\@auxout\xa{\xa\string\xa\qr@savematrix\qr@theargument}% % % Now set a flag, so we don't write this again. \xa\gdef\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname{TRUE}% }% \gdef\qr@dummyqrsavedefinition{}% \begingroup \catcode`\#=12\relax \catcode`\<=1\relax \catcode`\{=12\relax \catcode`\>=2\relax \catcode`\}=12\relax \catcode`\|=0\relax \catcode`\\=12|relax |gdef|qr@dummyqrsavedefinition<% \ifx\qr@savematrix\@undefined% \def\qr@savematrix{\begingroup\let\do\@makeother\dospecials\catcode`\{=1\catcode`\}=2\relax \qr@savematrix@int}% \def\qr@savematrix@int#1#2#3#4{\endgroup}% \fi% > |endgroup \edef\qr@argument{(\qr@dummyqrsavedefinition)}% \xa\write\xa\@auxout\xa{\qr@dummyqrsavedefinition}% \def\qr@savematrix{\bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qr@savematrix@int}% \def\qr@savematrix@int#1{\xdef\qr@savedmatrix@name{#1}\egroup\qr@savematrix@int@int}% \def\qr@savematrix@int@int#1#2#3{% % \qr@savedmatrix@name = encoded text % #1 = version % #2 = level % #3 = binary text \def\ds{^^J}\xa\message\xa{\ds}% {\let\%=\qr@otherpercent \xa\gdef\csname qr@savedbinarymatrix@\qr@savedmatrix@name @#1@#2\endcsname{#3}% }% }% % \end{macrocode} % % \Finale \endinput