summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/pkg/qrcode.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/optex/pkg/qrcode.opm')
-rw-r--r--macros/luatex/optex/pkg/qrcode.opm2706
1 files changed, 2706 insertions, 0 deletions
diff --git a/macros/luatex/optex/pkg/qrcode.opm b/macros/luatex/optex/pkg/qrcode.opm
new file mode 100644
index 0000000000..f757efe7b8
--- /dev/null
+++ b/macros/luatex/optex/pkg/qrcode.opm
@@ -0,0 +1,2706 @@
+% This is macro package used by OpTeX, see http://petr.olsak.net/optex
+% qrcode.opm, Petr Olšák <petr@olsak.net>, 2020
+
+% See end of the file for more information
+
+\_codedecl \qrcode {Macro for QR code printing <2020-05-04>}
+
+\_namespace{qr}
+
+\_newcount\.i
+\_newcount\.j
+\_newcount\.a
+\_newcount\.b
+\_newcount\.c
+
+\_def\.relax{\_relax}%
+
+\_def\.utfstring#1{\_directlua{
+ local text="\_luaescapestring{#1}"
+ tex.print(string.format('\_pcent.2x',string.len(text)))
+ for i=1,string.len(text) do
+ tex.print(string.format('\_pcent.2x',string.byte(text,i)))
+ end
+}}
+\_def\.utfstringlen#1{\_directlua{
+ tex.print(string.len("\_luaescapestring{#1}"))
+}}
+
+\_def\.g_preface_macro#1#2{%
+ % #1 = macro to be appended to
+ % #2 = code to add
+ \_edef\.codeA{#2}%
+ \_ea\_ea\_ea\_gdef\_ea\_ea\_ea#1\_ea\_ea\_ea{\_ea\.codeA#1}%
+}
+
+\_def\.getstringlength#1{%
+ \_xdef\.stringlength{\.utfstringlen{#1}}%
+}%
+
+\_def\.for#1=#2to#3by#4#{\.forA{#1}{#2}{#3}{#4}}
+\_long\_def\.forA#1#2#3#4#5{\_begingroup
+ {\_escapechar=`\\ % allocation of #1 as counter:
+ \_ea \_ifx\_csname for:\_string#1\_endcsname \_relax
+ \_csname newcount\_ea\_endcsname \_csname for:\_string#1\_endcsname\_fi
+ \_ea}\_ea\_let\_ea#1\_csname for:\_string#1\_endcsname
+ #1=#2%
+ \_def\.forB{#5\_advance#1by#4\_relax \_ea\.forC}%
+ \_ifnum#4>0 \_def\.forC{\_ifnum#1>#3\_relax\_else\.forB\_fi}%
+ \_else \_def\.forC{\_ifnum#1<#3\_relax\_else\.forB\_fi}%
+ \_fi
+ \_ifnum#4=0 \let\.forC=\_relax \_fi
+ \.forC \_endgroup
+}
+
+\_def\.padatfront#1#2{%
+ % #1 = macro containing text to pad
+ % #2 = desired number of characters
+ % Pads a number with initial zeros.
+ \.getstringlength{#1}%
+ \.a=\.stringlength\_relax
+ \_advance\.a by 1\_relax
+ \.for \.iz = \.a to #2 by 1
+ {\.g_preface_macro{#1}{0}}%
+}
+
+\.a=-1\_relax
+\_def\.savehexsymbols(#1#2){%
+ \_advance\.a by 1\_relax%
+ \_ea\_def\_csname _qr_hexchar:\_the\.a\_endcsname{#1}%
+ \_ea\_edef\_csname _qr_hextodecimal:#1\_endcsname{\_the\.a}%
+ \_ifnum\.a=15\_relax
+ %Done.
+ \_let\.next=\_relax
+ \_else
+ \_def\.next{\.savehexsymbols(#2)}%
+ \_fi
+ \.next
+}%
+\.savehexsymbols(0123456789abcdef\_relax\_relax)%
+
+\_def\.decimaltobase#1#2#3{%
+ % #1 = macro to store result
+ % #2 = decimal representation of a positive integer
+ % #3 = new base
+ \_bgroup
+ \_edef\.newbase{#3}%
+ \_gdef\.base_result{}%
+ \.a=#2\_relax%
+ \.decimaltobase_recursive%
+ \_xdef#1{\.base_result}%
+ \_egroup
+}
+\_def\.decimaltobase_recursive{%
+ \.b=\.a
+ \_divide\.b by \.newbase\_relax
+ \_multiply\.b by -\.newbase\_relax
+ \_advance\.b by \.a\_relax
+ \_divide\.a by \.newbase\_relax
+ \_ifnum\.b<10\_relax
+ \_edef\.newdigit{\_the\.b}%
+ \_else
+ \_edef\.newdigit{\_csname _qr_hexchar:\_the\.b\_endcsname}%
+ \_fi
+ \_edef\.argument{{\_noexpand\.base_result}{\.newdigit}}%
+ \_ea\.g_preface_macro\.argument
+ \_ifnum\.a=0\_relax
+ \_relax
+ \_else
+ \_ea\.decimaltobase_recursive
+ \_fi
+}
+\_long\_def\.xaddto#1#2{\_xdef#1{#1#2}}
+
+\_def\.decimaltohex[#1]#2#3{%
+ % #1 (opt.) = number of hex digits to create
+ % #2 = macro to store result
+ % #3 = decimal digits to convert
+ \.decimaltobase{#2}{#3}{16}%
+ \.padatfront{#2}{#1}%
+}
+\_def\.decimaltobinary[#1]#2#3{%
+ % #1 (opt.) = number of bits to create
+ % #2 = macro to store result
+ % #3 = decimal digits to convert
+ \.decimaltobase{#2}{#3}{2}%
+ \.padatfront{#2}{#1}%
+}
+
+\.for \.iz = 0 to 15 by 1%
+ {%
+ \.decimaltohex[1]{\.hexchar}{\_the\.iz}%
+ \.decimaltobinary[4]{\.bits}{\_the\.iz}%
+ \_ea\_xdef\_csname _qr_b2h:\.bits\_endcsname{\.hexchar}%
+ \_ea\_xdef\_csname _qr_h2b:\.hexchar\_endcsname{\.bits}%
+ }%
+
+\_def\.binarytohex[#1]#2#3{%
+ % #1 (optional) = # digits desired
+ % #2 = macro to save to
+ % #3 = binary string (must be multiple of 4 bits)
+ \_def\.testi{#1}%
+ \_ifx\.testi\.relax%
+ %No argument specified
+ \_def\.desireddigits{0}%
+ \_else
+ \_def\.desireddigits{#1}%
+ \_fi
+ \_gdef\.base_result{}%
+ \_edef\.argument{(#3\_relax\_relax\_relax\_relax\_relax)}%
+ \_ea\.binarytohex_int\.argument%
+ \.padatfront{\.base_result}{\.desireddigits}%
+ \_xdef#2{\.base_result}%
+}
+\_def\.binarytohex_int(#1#2#3#4#5){%
+ % #1#2#3#4 = 4 bits
+ % #5 = remainder, including \_relax\_relax\_relax\_relax\_relax terminator
+ \_def\.testi{#1}%
+ \_ifx\.testi\.relax%
+ %Done.
+ \_def\.next{\_relax}%
+ \_else%
+ \_xdef\.base_result{\.base_result\_csname _qr_b2h:#1#2#3#4\_endcsname}%
+ \_def\.next{\.binarytohex_int(#5)}%
+ \_fi%
+ \.next%
+}
+
+\_def\.hextobinary[#1]#2#3{%
+ % #1 (optional) = # bits desired
+ % #2 = macro to save to
+ % #3 = hexadecimal string
+ \_bgroup
+ \_def\.testi{#1}%
+ \_ifx\.testi\.relax
+ %No argument specified
+ \_def\.desireddigits{0}%
+ \_else
+ \_def\.desireddigits{#1}%
+ \_fi
+ \_gdef\.base_result{}%
+ \_edef\.argument{(#3\_relax\_relax)}%
+ \_ea\.hextobinary_int\.argument%
+ \.padatfront{\.base_result}{\.desireddigits}%
+ \_xdef#2{\.base_result}%
+ \_egroup
+}
+\_def\.hextobinary_int(#1#2){%
+ % #1 = hexadecimal character
+ % #2 = remainder, including \_relax\_relax terminator
+ \_def\.testii{#1}%
+ \_ifx\.testii\.relax
+ %Done.
+ \_def\.next{\_relax}%
+ \_else
+ \_xdef\.base_result{\.base_result\_csname _qr_h2b:#1\_endcsname}%
+ \_def\.next{\.hextobinary_int(#2)}%
+ \_fi
+ \.next
+}
+
+\_def\.hextodecimal#1#2{%
+ \_edef\.argument{#2}%
+ \_ea\.a\_ea=\_ea\_number\_ea"\.argument\_relax
+ \_edef#1{\_the\.a}%
+}
+
+\_def\.hextodecimal#1#2{%
+ % #1 = macro to store result
+ % #2 = hexadecimal representation of a positive integer
+ \_bgroup
+ \.a=0\_relax
+ \_edef\.argument{(#2\_relax)}%
+ \_ea\.hextodecimal_recursive\.argument%
+ \_xdef#1{\_the\.a}%
+ \_egroup
+}
+\_def\.hextodecimal_recursive(#1#2){%
+ % #1 = first hex char
+ % #2 = remainder
+ \_advance \.a by \_csname _qr_hextodecimal:#1\_endcsname\_relax%
+ \_edef\.testii{#2}%
+ \_ifx\.testii\.relax%
+ %Done.
+ \_let\.next=\_relax%
+ \_else
+ %There's at least one more digit.
+ \_multiply\.a by 16\_relax
+ \_edef\.next{\_noexpand\.hextodecimal_recursive(#2)}%
+ \_fi%
+ \.next%
+}
+
+\_def\.storetomatrix#1#2#3#4{%
+ % #1 = matrix name
+ % #2 = row number
+ % #3 = column number
+ % #4 = value of matrix entry
+ \_ea\_gdef\_csname #1@#2@#3\_endcsname{#4}%
+}%
+
+\_def\.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
+ \_ea\_gdef\_csname #1@#2@#3\_ea\_endcsname\_ea{#4}%
+}%
+
+\_def\.matrixentry#1#2#3{%
+ % #1 = matrix name
+ % #2 = row number
+ % #3 = column number
+ \_csname #1@#2@#3\_endcsname
+}%
+
+\_def\.createsquareblankmatrix#1#2{%
+% \.creatematrix{#1}%
+ \_ea\_gdef\_csname #1@numrows\_endcsname{#2}%
+ \_ea\_gdef\_csname #1@numcols\_endcsname{#2}%
+ \.for \.iz = 1 to #2 by 1%
+ {\.for \.jz = 1 to #2 by 1%
+ {\.storetomatrix{#1}{\_the\.iz}{\_the\.jz}{\.blank}}}%
+}%
+
+\_def\.numberofrowsinmatrix#1{%
+ \_csname #1@numrows\_endcsname%
+}%
+
+\_def\.numberofcolsinmatrix#1{%
+ \_csname #1@numcols\_endcsname%
+}%
+
+\_def\.setnumberofrows#1#2{%
+ \_ea\_xdef\_csname #1@numrows\_endcsname{#2}%
+}%
+
+\_def\.setnumberofcols#1#2{%
+ \_ea\_xdef\_csname #1@numcols\_endcsname{#2}%
+}%
+
+\_newdimen\.desiredheight
+\_newdimen\.modulesize
+
+\_def\.link#1#2{\_hbox{\_pdfstartlink height\_ht0 depth0pt \.border
+ user{/Subtype/Link/A <</Type/Action/S/URI/URI(#1)>>}\_relax #2\_pdfendlink}%
+}
+\_def\.border{%
+ \_ifcsname _qr_kv:qrborder\_endcsname attr{/C[\.kv{qrborder}] /Border[0 0 .6]}%
+ \_else attr{/Border[0 0 0]}%
+ \_fi
+}
+
+\_def\.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
+% \.creatematrix{#1}%
+ \_ea\_xdef\_csname #1@numrows\_endcsname{#2}%
+ \_ea\_xdef\_csname #1@numcols\_endcsname{#2}%
+ \_gdef\.literalmatrix_tokens{#3}%
+ \.for \.iz = 1 to #2 by 1%
+ {\.for \.jz = 1 to #2 by 1%
+ {\_ea\.createliteralmatrix_int\_ea(\.literalmatrix_tokens)%
+ \.estoretomatrix{#1}{\_the\.iz}{\_the\.jz}{\.entrytext}%
+ }%
+ }%
+}
+\_def\.createliteralmatrix_int(#1#2){%
+ \_def\.entrytext{#1}%
+ \_gdef\.literalmatrix_tokens{#2}%
+}
+
+\.createliteralmatrix{finderpattern}{8}{%
+ \.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.whitefixed
+ \.blackfixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.blackfixed\.whitefixed
+ \.blackfixed\.whitefixed\.blackfixed\.blackfixed\.blackfixed\.whitefixed\.blackfixed\.whitefixed
+ \.blackfixed\.whitefixed\.blackfixed\.blackfixed\.blackfixed\.whitefixed\.blackfixed\.whitefixed
+ \.blackfixed\.whitefixed\.blackfixed\.blackfixed\.blackfixed\.whitefixed\.blackfixed\.whitefixed
+ \.blackfixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.blackfixed\.whitefixed
+ \.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed\.whitefixed
+ \.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed\.whitefixed
+}%
+
+\.createliteralmatrix{alignmentpattern}{5}{%
+ \.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed
+ \.blackfixed\.whitefixed\.whitefixed\.whitefixed\.blackfixed
+ \.blackfixed\.whitefixed\.blackfixed\.whitefixed\.blackfixed
+ \.blackfixed\.whitefixed\.whitefixed\.whitefixed\.blackfixed
+ \.blackfixed\.blackfixed\.blackfixed\.blackfixed\.blackfixed
+}%
+
+\_def\.copymatrixentry#1#2#3#4#5#6{%
+ % Copy the (#2,#3) entry of matrix #1
+ % to the (#5,#6) position of matrix #4.
+ \_ea\_ea\_ea\_global%
+ \_ea\_ea\_ea\_let\_ea\_ea\_csname #4@#5@#6\_endcsname
+ \_csname #1@#2@#3\_endcsname
+}%
+
+\_def\.createduplicatematrix#1#2{%
+ % #1 = name of copy
+ % #2 = original matrix to be copied
+% \.creatematrix{#1}%
+ \.for \.iz = 1 to \.numberofrowsinmatrix{#2} by 1%
+ {\.for \.jz = 1 to \.numberofcolsinmatrix{#2} by 1%
+ {\.copymatrixentry{#2}{\_the\.iz}{\_the\.jz}{#1}{\_the\.iz}{\_the\.jz}%
+ }%
+ }%
+ \.setnumberofrows{#1}{\.numberofrowsinmatrix{#2}}%
+ \.setnumberofcols{#1}{\.numberofcolsinmatrix{#2}}%
+}%
+
+\_def\.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 counters indicating positions in the big matrix.
+ \.setcounter\.i{#2}%
+ \.for \.sourcei=1 to 8 by 1%
+ {\.setcounter\.j{#3}%
+ \.for \.sourcej=1 to 8 by 1%
+ {\.copymatrixentry{finderpattern}{\_the\.sourcei}{\_the\.sourcej}%
+ {#1}{\_the\.i}{\_the\.j}%
+ \.addtocounter\.j{#5}%
+ }%
+ \.addtocounter\.i{#4}%
+ }%
+}%
+
+\_def\.placefinderpatterns#1{%
+ % #1=matrix name
+ \.placefinderpattern_int{#1}{1}{1}{1}{1}%
+ \.placefinderpattern_int{#1}{\.numberofrowsinmatrix{#1}}{1}{-1}{1}%
+ \.placefinderpattern_int{#1}{1}{\.numberofcolsinmatrix{#1}}{1}{-1}%
+}%
+
+\_def\.placetimingpatterns#1{%
+ %Set \.endingcol to n-8.
+ \.a=\.size\_relax%
+ \_advance\.a by -8\_relax%
+ \_edef\.endingcol{\_the\.a}%
+ \.for \.jz = 9 to \.endingcol by 1%
+ {\_ifodd\.jz\_relax%
+ \.storetomatrix{#1}{7}{\_the\.jz}{\.blackfixed}%
+ \.storetomatrix{#1}{\_the\.jz}{7}{\.blackfixed}%
+ \_else%
+ \.storetomatrix{#1}{7}{\_the\.jz}{\.whitefixed}%
+ \.storetomatrix{#1}{\_the\.jz}{7}{\.whitefixed}%
+ \_fi%
+ }%
+}%
+
+\_def\.placealignmentpattern_int#1#2#3{%
+ % Work on matrix #1.
+ % Write an alignment pattern into the matrix, centered on (#2,#3).
+ \.a=#2\_relax%
+ \_advance\.a by -2\_relax%
+ \.b=#3\_relax%
+ \_advance\.b by -2\_relax%
+ \.setcounter\.i{\_the\.a}%
+ \.for \.iz=1 to 5 by 1%
+ {\.setcounter\.j{\_the\.b}%
+ \.for \.jz=1 to 5 by 1%
+ {\.copymatrixentry{alignmentpattern}{\_the\.iz}{\_the\.jz}%
+ {#1}{\_the\.i}{\_the\.j}%
+ \.stepcounter\.j
+ }%
+ \.stepcounter\.i
+ }%
+}%
+
+\_newifi\_ifqr_incorner%
+\_def\.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
+ % * \.k stores k,
+ % * \.alignment_firstskip stores how far between the 1st and 2nd row/col, &
+ % * \.alignment_generalskip stores how far between each subsequent row/col.
+ \_ea\_ifnum\.k>0\_relax
+ %There will be at least one alignment pattern.
+ %N.B. k cannot equal 1.
+ \_ea\_ifnum\.k=2\_relax
+ % 2*2-3 = exactly 1 alignment pattern.
+ \.a=7\_relax
+ \_advance\.a by \.alignment_firstskip\_relax
+ \_xdef\.targetii{\_the\.a}%
+ \.placealignmentpattern_int{#1}{\.targetii}{\.targetii}%
+ \_else
+ % k is at least 3, so the following loops should be safe.
+ \_xdef\.targetii{7}%
+ \.for \.ii = 1 to \.k by 1%
+ {\_ifcase\.ii\_relax%
+ \_relax% \.ii should never equal 0.
+ \_or
+ \_xdef\.targetii{7}% If \.ii = 1, we start in row 7.
+ \_or
+ %If \.ii = 2, we add the firstskip.
+ \.a=\.targetii\_relax%
+ \_advance\.a by \.alignment_firstskip\_relax%
+ \_xdef\.targetii{\_the\.a}%
+ \_else
+ %If \.ii>2, we add the generalskip.
+ \.a=\.targetii\_relax%
+ \_advance\.a by \.alignment_generalskip\_relax%
+ \_xdef\.targetii{\_the\.a}%
+ \_fi
+ \.for \.jj = 1 to \.k by 1%
+ {\_ifcase\.jj\_relax%
+ \_relax% \.jj should never equal 0.
+ \_or
+ \_xdef\.targetjj{7}% If \.jj=1, we start in row 7.
+ \_or
+ %If \.jj=2, we add the firstskip.
+ \.a=\.targetjj\_relax%
+ \_advance\.a by \.alignment_firstskip%
+ \_xdef\.targetjj{\_the\.a}%
+ \_else
+ %If \.jj>2, we add the generalskip.
+ \.a=\.targetjj\_relax%
+ \_advance\.a by \.alignment_generalskip%
+ \_xdef\.targetjj{\_the\.a}%
+ \_fi
+ \.incornerfalse%
+ \_ifnum\.ii=1\_relax
+ \_ifnum\.jj=1\_relax
+ \.incornertrue
+ \_else
+ \_ifnum\.k=\.jj\_relax
+ \.incornertrue
+ \_fi
+ \_fi
+ \_else
+ \_ea\_ifnum\.k=\.ii\_relax
+ \_ifnum\.jj=1\_relax
+ \.incornertrue
+ \_fi
+ \_fi
+ \_fi
+ \_ifqr_incorner
+ \_relax
+ \_else
+ \.placealignmentpattern_int{#1}{\.targetii}{\.targetjj}%
+ \_fi
+ }% ends \.for \.jj
+ }% ends \.for \.ii
+ \_fi
+ \_fi
+}%
+
+\_def\.placedummyformatpatterns#1{%
+ \.for \.jz = 1 to 9 by 1%
+ {\_ifnum\.jz=7\_relax%
+ \_else%
+ \.storetomatrix{#1}{9}{\_the\.jz}{\.formatsquare}%
+ \.storetomatrix{#1}{\_the\.jz}{9}{\.formatsquare}%
+ \_fi%
+ }%
+ \.setcounter\.j{\.size}%
+ \.for \.jz = 1 to 8 by 1%
+ {\.storetomatrix{#1}{9}{\_the\.j}{\.formatsquare}%
+ \.storetomatrix{#1}{\_the\.j}{9}{\.formatsquare}%
+ \.addtocounter\.j{-1}%
+ }%
+ %Now go back and change the \.formatsquare in (n-8,9) to \.blackfixed.
+ \.addtocounter\.j{1}%
+ \.storetomatrix{#1}{\_the\.j}{9}{\.blackfixed}%
+}%
+
+\_def\.placedummyversionpatterns#1{%
+ \_ea\_ifnum\.version>6\_relax
+ %Must include version information.
+ \_global\.i=\.size%
+ \_global\_advance\.i by -10\_relax%
+ \.for \.iz = 1 to 3 by 1%
+ {\.for \.jz = 1 to 6 by 1%
+ {\.storetomatrix{#1}{\_the\.i}{\_the\.jz}{\.formatsquare}%
+ \.storetomatrix{#1}{\_the\.jz}{\_the\.i}{\.formatsquare}%
+ }%
+ \.stepcounter\.i
+ }%
+ \_fi
+}%
+
+\_def\.writebit(#1#2)#3{%
+ % #3 = matrix name
+ % (qr_i,qr_j) = position to write in (counters)
+ % #1 = bit to be written
+ % #2 = remaining bits plus '\_relax' as an end-of-file marker
+ \_edef\.datatowrite{#2}%
+ \_ifnum#1=1
+ \.storetomatrix{#3}{\_the\.i}{\_the\.j}{\.black}%
+ \_else
+ \.storetomatrix{#3}{\_the\.i}{\_the\.j}{\.white}%
+ \_fi
+}%
+
+\_newifi\_ifqr_rightcol
+\_newifi\_ifqr_goingup
+
+\_def\.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\.i{\.numberofrowsinmatrix{#1}}%
+ \.setcounter\.j{\.numberofcolsinmatrix{#1}}%
+ \.rightcoltrue
+ \.goinguptrue
+ \_edef\.argument{{#1}(#2\_relax\_relax\_relax)}%
+ \_ea\.writedata_hex_recursive\.argument%
+}%
+
+\_def\.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 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\.testii{#2}%
+ \_ifx\.testii\.relax%
+ % #2 is \_relax, so there is nothing more to write.
+ \_relax
+ \_let\.go=\_relax
+ \_else
+ % #2 is not \_relax, so there is another byte to write.
+ \.hextobinary[8]{\.bytetowrite}{#2#3}%
+ \_xdef\.datatowrite{\.bytetowrite\_relax}% %Add terminating "\_relax"
+ \.writedata_recursive{#1}% %This function actually writes the 8 bits.
+ \_edef\.argument{{#1}(#4)}%
+ \_ea\_def\_ea\.go\_ea{\_ea\.writedata_hex_recursive\.argument}% %Call self to write the next bit.
+ \_fi
+ \.go
+}%
+
+\_def\.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\.i{\.numberofrowsinmatrix{#1}}%
+ \.setcounter\.j{\.numberofcolsinmatrix{#1}}%
+ \.rightcoltrue
+ \.goinguptrue
+ \_edef\.datatowrite{#2\_relax}%
+ \.writedata_recursive{#1}%
+}%
+
+\_def\.iblank{\.blank}%
+
+\_def\.writedata_recursive#1{%
+ % #1 = matrix name
+ % (qr_i,qr_j) = position to write in (counters)
+ % \.datatowrite contains the bits to be written, plus '\_relax' as an end-of-file marker
+ \_ea\_let\_ea\.squarevalue\_csname #1@\_the\.i @\_the\.j\_endcsname%
+ \_ifx\.squarevalue\.iblank
+ %Square is blank, so write data in it.
+ \_ea\.writebit\_ea(\.datatowrite){#1}%
+ %The \.writebit macro not only writes the first bit of \.datatowrite into the matrix,
+ %but also removes the bit from the 'bitstream' of \.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\.j{-1}%
+ \.rightcolfalse
+ \_else
+ %If we're in the left-hand column, things are harder.
+ \_ifqr_goingup
+ %First, suppose we're going upwards.
+ \_ifnum\.i>1\_relax%
+ %If we're not in the first row, things are easy.
+ %We move one to the right and one up.
+ \.addtocounter\.j{1}%
+ \.addtocounter\.i{-1}%
+ \.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\.j{-1}%
+ \.goingupfalse
+ \.rightcoltrue
+ \_fi
+ \_else
+ %Now, suppose we're going downwards.
+ \_ea\_ifnum\.size>\.i\_relax%
+ %If we're not yet in the bottom row, things are easy.
+ %We move one to the right and one down.
+ \.addtocounter\.j{1}%
+ \.addtocounter\.i{1}%
+ \.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\.j{-1}%
+ \.rightcoltrue
+ \.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\.j=7\_relax%
+ \.setcounter\.j{6}%
+ \_fi
+ \_fi
+ %Now check whether there are any more bits to write.
+ \_ifx\.datatowrite\.relax
+ % \.datatowrite is just `\_relax', so we're done.
+ \_let\.nexttoken=\_relax
+ \_relax
+ \_else
+ % Write some more!
+ \_def\.nexttoken{\.writedata_recursive{#1}}%
+ \_fi
+ \.nexttoken
+}%
+
+\_def\.writeremainderbits#1{%
+ % #1 = name of a matrix that has been prepared and partly filled.
+ % (qr_i,qr_j) = position to write in counters
+ \_ea\_ifnum\.numremainderbits>0\_relax
+ \_def\.datatowrite{}%
+ \.for \.iz = 1 to \.numremainderbits by 1%
+ {\.xaddto{\.datatowrite}{0}}%
+ \.xaddto{\.datatowrite}{\_relax}% terminator
+ \.writedata_recursive{#1}%
+ \_fi
+}%
+
+\_newifi\_ifqr_cellinmask
+
+\_def\.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\.maskselection{#1}%
+ \_ea\_ifcase\.maskselection\_relax
+ %Case 0: checkerboard
+ \_def\.parsemaskingfunction{%
+ % Compute mod(\themaski+\themaskj,2)%
+ \.a=\.maski%
+ \_advance\.a by \.maskj%
+ \.b=\.a%
+ \_divide\.b by 2%
+ \_multiply\.b by 2%
+ \_advance\.a by -\.b%
+ \_edef\.maskfunctionresult{\_the\.a}%
+ }%
+ \_or
+ %Case 1: horizontal stripes
+ \_def\.parsemaskingfunction{%
+ % Compute mod(\themaski,2)%
+ \_ifodd\.maski\_relax%
+ \_def\.maskfunctionresult{1}%
+ \_else%
+ \_def\.maskfunctionresult{0}%
+ \_fi%
+ }%
+ \_or
+ %Case 2: vertical stripes
+ \_def\.parsemaskingfunction{%
+ % Compute mod(\themaskj,3)%
+ \.a=\.maskj%
+ \_divide\.a by 3%
+ \_multiply\.a by 3%
+ \_advance\.a by -\.maskj%
+ \_edef\.maskfunctionresult{\_the\.a}%
+ }%
+ \_or
+ %Case 3: diagonal stripes
+ \_def\.parsemaskingfunction{%
+ % Compute mod(\themaski+\themaskj,3)%
+ \.a=\.maski%
+ \_advance\.a by \.maskj%
+ \.b=\.a%
+ \_divide\.b by 3%
+ \_multiply\.b by 3%
+ \_advance\.b by -\.a%
+ \_edef\.maskfunctionresult{\_the\.b}%
+ }%
+ \_or
+ %Case 4: wide checkerboard
+ \_def\.parsemaskingfunction{%
+ % Compute mod(floor(\themaski/2) + floor(\themaskj/3),2) %
+ \.a=\.maski%
+ \_divide\.a by 2%
+ \.b=\.maskj%
+ \_divide\.b by 3%
+ \_advance\.a by \.b%
+ \.b=\.a%
+ \_divide\.a by 2%
+ \_multiply\.a by 2%
+ \_advance\.a by -\.b%
+ \_edef\.maskfunctionresult{\_the\.a}%
+ }%
+ \_or
+ %Case 5: quilt
+ \_def\.parsemaskingfunction{%
+ % Compute mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) %
+ \.a=\.maski%
+ \_multiply\.a by \.maskj%
+ \.b=\.a%
+ \.c=\.a%
+ \_divide\.a by 2%
+ \_multiply\.a by 2%
+ \_advance\.a by -\.c% (result will be -mod(i*j,2), which is negative.)
+ \_divide\.b by 3%
+ \_multiply\.b by 3%
+ \_advance\.b by -\.c% (result will be -mod(i*j,3), which is negative.)
+ \_advance\.a by \.b% (result is negative of what's in the spec.)
+ \_edef\.maskfunctionresult{\_the\.a}%
+ }%
+ \_or
+ %Case 6: arrows
+ \_def\.parsemaskingfunction{%
+ % Compute mod( mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) %
+ \.a=\.maski%
+ \_multiply\.a by \.maskj%
+ \.b=\.a%
+ \.c=\.a%
+ \_multiply\.c by 2% % \.c equals 2*i*j.
+ \_divide\.a by 2%
+ \_multiply\.a by 2%
+ \_advance\.c by -\.a% Now \.c equals i*j + mod(i*j,2).
+ \_divide\.b by 3%
+ \_multiply\.b by 3%
+ \_advance\.c by -\.b% (Now \.c equals mod(i*j,2) + mod(i*j,3).
+ \.a=\.c%
+ \_divide\.a by 2%
+ \_multiply\.a by 2%
+ \_advance\.c by-\.a%
+ \_edef\.maskfunctionresult{\_the\.c}%
+ }%
+ \_or
+ %Case 7: shotgun
+ \_def\.parsemaskingfunction{%
+ % Compute mod( mod(\themaski+\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) %
+ \.a=\.maski%
+ \_advance\.a by \.maskj% %So \.a = i+j
+ \.b=\.maski%
+ \_multiply\.b by \.maskj% %So \.b = i*j
+ \.c=\.a%
+ \_advance\.c by \.b% So \.c = i+j+i*j
+ \_divide\.a by 2%
+ \_multiply\.a by 2%
+ \_advance\.c by -\.a% So \.c = mod(i+j,2) + i*j
+ \_divide\.b by 3%
+ \_multiply\.b by 3%
+ \_advance\.c by -\.b% So \.c = mod(i+j,2) + mod(i*j,3)
+ \.a=\.c%
+ \_divide\.c by 2%
+ \_multiply\.c by 2%
+ \_advance\.a by -\.c%
+ \_edef\.maskfunctionresult{\_the\.a}%
+ }%
+ \_fi
+}%
+
+\_def\.checkifcellisinmask{%
+ % The current position is (\.iz,\.jz), in TeX counts,
+ % but the counters (maski,maskj) should contain
+ % the current position with indexing starting at 0.
+ % That is, maski = \.iz-1 and maskj = \.jz-1.
+ %
+ % \.parsemaskingfunction must have been set by a call to \.setmaskingfunction
+ \.parsemaskingfunction
+ \_ea\_ifnum\.maskfunctionresult=0\_relax
+ \.cellinmasktrue
+ \_else
+ \.cellinmaskfalse
+ \_fi
+}%
+
+\_newcount\.maski
+\_newcount\.maskj
+
+\_def\.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
+ \.createduplicatematrix{#2}{#1}%
+ \.setmaskingfunction{#3}%
+ \.setcounter\.maski{-1}%
+ \.for \.iz = 1 to \.size by 1%
+ {\.stepcounter\.maski
+ \.setcounter\.maskj{-1}%
+ \.for \.jz = 1 to \.size by 1%
+ {\.stepcounter\.maskj
+ \.checkifcellisinmask
+ \_ifqr_cellinmask
+ \.checkifcurrentcellcontainsdata{#2}%
+ \_ifqr_currentcellcontainsdata
+ \.flipcurrentcell{#2}%
+ \_fi
+ \_fi
+ }%
+ }%
+}%
+
+\_newifi\_ifqr_currentcellcontainsdata
+\.currentcellcontainsdatafalse
+
+\_def\.iwhite{\.white}%
+\_def\.iblack{\.black}%
+
+\_def\.checkifcurrentcellcontainsdata#1{%
+ % #1 = name of matrix
+ \.currentcellcontainsdatafalse
+ \_ea\_ifx\_csname #1@\_the\.iz @\_the\.jz\_endcsname\.iwhite
+ \.currentcellcontainsdatatrue
+ \_fi
+ \_ea\_ifx\_csname #1@\_the\.iz @\_the\.jz\_endcsname\.iblack
+ \.currentcellcontainsdatatrue
+ \_fi
+}%
+
+\_def\.flippedblack{\.black}%
+\_def\.flippedwhite{\.white}%
+
+\_def\.flipcurrentcell#1{%
+ % #1 = name of matrix
+ % (\.iz, \.jz) = current position, in TeX counts.
+ % This assumes the cell contains data, either black or white!
+ \_ea\_ifx\_csname #1@\_the\.iz @\_the\.jz\_endcsname\.iwhite
+ \.storetomatrix{#1}{\_the\.iz}{\_the\.jz}{\.flippedblack}%
+ \_else
+ \.storetomatrix{#1}{\_the\.iz}{\_the\.jz}{\.flippedwhite}%
+ \_fi
+}%
+
+\_def\.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 \.mask_selected.
+ \.createduplicatematrix{originalmatrix}{#1}%
+ \.message{<Applying Mask 0...}%
+ \.applymask{originalmatrix}{#1}{0}%
+ \.message{done. Calculating penalty...}%
+ \.evaluatemaskpenalty{#1}%
+ \_xdef\.currentbestpenalty{\.penalty}%
+ \.message{penalty is \.penalty>^^J}%
+ \_gdef\.currentbestmask{0}%
+ \.for \.iz = 1 to 7 by 1%
+ {\.message{<Applying Mask \_the\.iz...}%
+ \.applymask{originalmatrix}{currentmasked}{\_the\.iz}%
+ \.message{done. Calculating penalty...}%
+ \.evaluatemaskpenalty{currentmasked}%
+ \.message{penalty is \.penalty>^^J}%
+ \_ea\_ea\_ea\_ifnum\_ea\.penalty\_ea<\.currentbestpenalty\_relax
+ %We found a better mask.
+ \_xdef\.currentbestmask{\_the\.iz}%
+ \.createduplicatematrix{#1}{currentmasked}%
+ \_xdef\.currentbestpenalty{\.penalty}%
+ \_fi
+ }%
+ \_xdef\.mask_selected{\.currentbestmask}%
+ \.message{<Selected Mask \.mask_selected>^^J}%
+}%
+
+\_def\.Ni{3}%
+\_def\.Nii{3}%
+\_def\.Niii{40}%
+\_def\.Niv{10}%
+\_def\.fiveones{11111}%
+\_def\.fivezeros{00000}%
+\_def\.twoones{11}%
+\_def\.twozeros{00}%
+\_def\.finderA{00001011101}%
+\_def\.finderB{10111010000}%
+\_def\.finderBthree{1011101000}%
+\_def\.finderBtwo{101110100}%
+\_def\.finderBone{10111010}%
+\_def\.finderBzero{1011101}%
+\_newifi\_ifqr_stringoffive
+\_def\.addpenaltyiii{%
+ \.addtocounter\.penaltyiii{\.Niii}%
+}%
+\_newcount\.totalones
+\_newcount\.penaltyi
+\_newcount\.penaltyii
+\_newcount\.penaltyiii
+\_newcount\.penaltyiv
+\_def\.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\.black{1}\_def\.white{0}%
+ \_def\.blackfixed{1}\_def\.whitefixed{0}%
+ \_def\.formatsquare{0}% This is not stated in the specs, but seems
+ % to be the standard implementation.
+ \_def\.blank{0}% These would be any bits at the end.
+ %
+ \.setcounter\.totalones{0}%
+ \.for \.iz=1 to \.size by 1%
+ {\_def\.lastfive{z}% %The z is a dummy, that will be removed before any testing.
+ \.stringoffivefalse
+ \_def\.lasttwo_thisrow{z}% %The z is a dummy.
+ \_def\.lasttwo_nextrow{z}% %The z is a dummy.
+ \_def\.lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy.
+ \_def\.ignore_finderBat{0}%
+ \.for \.jz=1 to \.size by 1%
+ {\_edef\.newbit{\.matrixentry{#1}{\_the\.iz}{\_the\.jz}}%
+ %
+ % LASTFIVE CODE FOR PENALTY 1
+ % First, add the new bit to the end.
+ \_ea\.xaddto\_ea\.lastfive\_ea{\.newbit}%
+ \_ifnum\.jz<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.
+ \.removefirsttoken\.lastfive%
+ \_ifx\.lastfive\.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{\.Ni}%
+ \_global\.stringoffivetrue
+ \_fi
+ \_else
+ \_ifx\.lastfive\.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{\.Ni}%
+ \_global\.stringoffivetrue
+ \_fi
+ \_else
+ %This is not a string of five 1's or five 0's.
+ \_global\.stringoffivefalse
+ \_fi
+ \_fi
+ \_fi
+ %
+ % 2x2 BLOCKS FOR PENALTY 2
+ % Every 2x2 block of all 1's counts for \.Nii penalty points.
+ % We do not need to run this test in the last row.
+ \_ea\_ifnum\_ea\.iz\_ea<\.size\_relax
+ \_ea\.xaddto\_ea\.lasttwo_thisrow\_ea{\.newbit}%
+ %Compute \.iplusone
+ \.a=\.iz\_relax%
+ \_advance\.a by 1%
+ \_edef\.iplusone{\_the\.a}%
+ %
+ \_edef\.nextrowbit{\.matrixentry{#1}{\.iplusone}{\_the\.jz}}%
+ \_ea\.xaddto\_ea\.lasttwo_nextrow\_ea{\.nextrowbit}%
+ \_ifnum\.jz<2\_relax%
+ %Still in the first column; no check.
+ \_else
+ %Second column or later. Remove the old bits, and then test.
+ \.removefirsttoken\.lasttwo_thisrow
+ \.removefirsttoken\.lasttwo_nextrow
+ \_ifx\.lasttwo_thisrow\.twoones
+ \_ifx\.lasttwo_nextrow\.twoones
+ \.addtocounter\.penaltyii{\.Nii}%
+ \_fi
+ \_else
+ \_ifx\.lasttwo_thisrow\.twozeros
+ \_ifx\.lasttwo_nextrow\.twozeros
+ \.addtocounter\.penaltyii{\.Nii}%
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ %
+ % LASTNINE CODE FOR PENALTY 3
+ % First, add the new bit to the end.
+ \_ea\.xaddto\_ea\.lastnine\_ea{\.newbit}%
+ \_ifnum\.jz<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.
+ \.removefirsttoken\.lastnine
+ \_ea\_ifnum\.size=\.jz\_relax%
+ % Last column. Any of the following should count:
+ % 1011101 (\.finderBzero)
+ % 10111010 (\.finderBone)
+ % 101110100 (\.finderBtwo)
+ % 1011101000 (\.finderBthree)
+ % 10111010000 (\.finderB)
+ \_ifx\.lastnine\.finderB
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBthree
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBtwo
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBone
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBzero
+ \.addpenaltyiii
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_else
+ \_ifx\.lastnine\.finderA% %Matches 0000 1011101
+ \.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 \.ignore_finderBat to \.jz+4.
+ \.a=\.jz\_relax%
+ \_advance\.a by 4%
+ \_xdef\.ignore_finderBat{\_the\.a}%
+ \_else
+ \_ifx\.lastfive\.finderB% %Matches 1011101 0000.
+ \_ea\_ifnum\.ignore_finderBat=\.jz\_relax
+ %This pattern was *not* counted already earlier.
+ \.addpenaltyiii
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ %
+ %COUNT 1's FOR PENALTY 4
+ \_ea\_ifnum\.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.
+ \.for \.jz=1 to \.size by 1%
+ {\_def\.lastfive{z}% %The z is a dummy, that will be removed before any testing.
+ \.stringoffivefalse
+ \_def\.lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy.
+ \_def\.ignore_finderBat{0}%
+ \.for \.iz=1 to \.size by 1%
+ {\_edef\.newbit{\.matrixentry{#1}{\_the\.iz}{\_the\.jz}}%
+ %
+ % LASTFIVE CODE FOR PENALTY 1
+ % First, add the new bit to the end.
+ \_ea\.xaddto\_ea\.lastfive\_ea{\.newbit}%
+ \_ifnum\.iz<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.
+ \.removefirsttoken\.lastfive
+ \_ifx\.lastfive\.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{\.Ni}%
+ \_global\.stringoffivetrue
+ \_fi
+ \_else
+ \_ifx\.lastfive\.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{\.Ni}%
+ \_global\.stringoffivetrue
+ \_fi
+ \_else
+ %This is not a string of five 1's or five 0's.
+ \_global\.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.
+ \_ea\.xaddto\_ea\.lastnine\_ea{\.newbit}%
+ \_ifnum\.iz<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.
+ \.removefirsttoken\.lastnine
+ \_ea\_ifnum\.size=\.iz\_relax%
+ % Last column. Any of the following should count:
+ % 1011101 (\.finderBzero)
+ % 10111010 (\.finderBone)
+ % 101110100 (\.finderBtwo)
+ % 1011101000 (\.finderBthree)
+ % 10111010000 (\.finderB)
+ \_ifx\.lastnine\.finderB
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBthree
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBtwo
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBone
+ \.addpenaltyiii
+ \_else
+ \.removefirsttoken\.lastnine
+ \_ifx\.lastnine\.finderBzero
+ \.addpenaltyiii
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_fi
+ \_else
+ \_ifx\.lastnine\.finderA% %Matches 0000 1011101
+ \.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 \.ignore_finderBat to \.iz+4.
+ \.a=\.iz\_relax%
+ \_advance\.a by 4%
+ \_xdef\.ignore_finderBat{\_the\.a}%
+ \_else
+ \_ifx\.lastfive\.finderB% %Matches 1011101 0000.
+ \_ea\_ifnum\.ignore_finderBat=\.iz\_relax
+ %This pattern was *not* counted already earlier.
+ \.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.
+ %
+ \.a=\.totalones\_relax
+ \_multiply\.a by 20\_relax
+ \.b=\.size\_relax
+ \_multiply\.b by \.size\_relax
+ \.c=10\_relax
+ \_multiply\.c by \.b\_relax
+ \_advance\.a by -\.c\_relax
+ \_ifnum\.a<0\_relax
+ \_multiply\.a by -1\_relax
+ \_fi
+ \_divide\.a by \.b\_relax
+ \.setcounter\.penaltyiv{\_the\.a}%
+ %
+ %CALCULATE TOTAL PENALTY
+ \.a=\_the\.penaltyi\_relax%
+ \_advance\.a by \_the\.penaltyii\_relax%
+ \_advance\.a by \_the\.penaltyiii\_relax%
+ \_advance\.a by \_the\.penaltyiv\_relax%
+ \_edef\.penalty{\_the\.a}%
+}%
+
+\_def\.removefirsttoken#1{%
+ %Removes the first token from the macro named in #1.
+ \_edef\.argument{(#1)}%
+ \_ea\.removefirsttoken_int\.argument%
+ \_xdef#1{\.removefirsttoken_result}%
+}%
+\_def\.removefirsttoken_int(#1#2){%
+ \_def\.removefirsttoken_result{#2}%
+}%
+
+\_def\.writeformatstring#1#2{%
+ % #1 = matrix name
+ % #2 = binary string representing the encoded and masked format information
+ \.setcounter\.i{9}%
+ \.setcounter\.j{1}%
+ \_edef\.argument{{#1}(#2\_relax)}%
+ \_ea\.writeformatA_recursive\.argument
+ %
+ \.setcounter\.i{\.numberofrowsinmatrix{#1}}%
+ \.setcounter\.j{9}%
+ \_ea\.writeformatB_recursive\.argument
+}%
+
+\_def\.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 counters)
+ \_ifnum#2=1\_relax
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.blackformat}%
+ \_else
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.whiteformat}%
+ \_fi
+ % Now the tricky part--moving \.iz and \.jz to their next positions.
+ \_ifnum\.j<9\_relax
+ %If we're not yet in column 9, move right.
+ \.stepcounter\.j
+ \_ifnum\.j=7\_relax
+ %But we skip column 7!
+ \.stepcounter\.j
+ \_fi
+ \_else
+ %If we're in column 9, we move up.
+ \.addtocounter\.i{-1}%
+ \_ifnum\.i=7\_relax
+ %But we skip row 7!
+ \.addtocounter\.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\.i<1
+ \_let\.nexttoken=\_relax
+ \_else
+ \_def\.nexttoken{\.writeformatA_recursive{#1}(#3)}%
+ \_fi
+ \.nexttoken
+}%
+
+\_def\.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 counters)
+ \_ifnum#2=1\_relax
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.blackformat}%
+ \_else
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.whiteformat}%
+ \_fi
+ % Now the tricky part--moving counters i and j to their next positions.
+ \.a=\.size%
+ \_advance\.a by -6\_relax%
+ \_ifnum\.a<\.i\_relax
+ %If we're not yet in row n-6, move up.
+ \.addtocounter\.i{-1}%
+ \_else
+ \_ifnum\.a=\.i\_relax
+ %If we're actually in row n-6, we jump to position (9,n-7).
+ \.setcounter\.i{9}%
+ %Set counter j equal to \.size-7.
+ \_global\.j=\.size\_relax%
+ \_global\_advance\.j by -7\_relax%
+ \_else
+ %Otherwise, we must be in row 9.
+ %In this case, we move right.
+ \.stepcounter\.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.
+ \_ea\_ifnum\.size<\.j\_relax
+ \_let\.nexttoken=\_relax
+ \_else
+ \_def\.nexttoken{\.writeformatB_recursive{#1}(#3)}%
+ \_fi
+ \.nexttoken
+}%
+
+\_def\.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.
+ \_ea\_ifnum\.version>6\_relax
+ %Move to position (n-8,6).
+ \.setcounter\.i{\.size}\_relax%
+ \.addtocounter\.i{-8}\_relax%
+ \.setcounter\.j{6}%
+ \_edef\.argument{{#1}(#2\_relax)}%
+ \_ea\.writeversion_recursive\.argument
+ \_fi
+}%
+
+\_def\.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 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 \.topline equal to n-10.
+ \.a=\.size\_relax%
+ \_advance\.a by -10\_relax%
+ \_edef\.topline{\_the\.a}%
+ %
+ \_ifnum#2=1\_relax
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.blackformat}%
+ \.storetomatrix{#1}{\_the\.j}{\_the\.i}{\.blackformat}%
+ \_else
+ \.storetomatrix{#1}{\_the\.i}{\_the\.j}{\.whiteformat}%
+ \.storetomatrix{#1}{\_the\.j}{\_the\.i}{\.whiteformat}%
+ \_fi
+ % Now the tricky part--moving counters i and j to their next positions.
+ \.addtocounter\.i{-1}%
+ \_ea\_ifnum\.topline>\.i\_relax
+ %We've overshot the top of the region.
+ %We need to move left one column and down three.
+ \.addtocounter\.j{-1}%
+ \.addtocounter\.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\.j<1\_relax
+ \_let\.nexttoken=\_relax
+ \_else
+ \_def\.nexttoken{\.writeversion_recursive{#1}(#3)}%
+ \_fi
+ \.nexttoken
+}%
+\_newcount\.hexchars
+
+\_def\.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.
+ %
+ %Now comes the actual data.
+ %
+ {\_endlinechar=-1 \_xdef\.codetext{4\.utfstring{#1}0}}%
+ %The terminator is 0
+ %\.xaddto\.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\.hexchars{0}%
+ \.getstringlength{\.codetext}%
+ \.setcounter\.hexchars{\.stringlength}%
+ %Set \.numpaddingcodewords equal to \.totaldatacodewords - hexchars/2.
+ \.a=-\.hexchars\_relax
+ \_divide\.a by 2\_relax
+ \_advance\.a by \.totaldatacodewords\_relax
+ \_edef\.numpaddingcodewords{\_the\.a}%
+ %
+ \_ea\_ifnum\.numpaddingcodewords<0%
+ \_edef\.ds{ERROR: Too much data! Over by \.numpaddingcodewords bytes.}\_show\.ds
+ \_fi
+ \_ea\_ifnum\.numpaddingcodewords>0%
+ \.for \.iz = 2 to \.numpaddingcodewords by 2%
+ {\.xaddto{\.codetext}{ec11}}%
+ \_ea\_ifodd\.numpaddingcodewords\_relax
+ \.xaddto{\.codetext}{ec}%
+ \_fi
+ \_fi
+}%
+
+\_def\.splitcodetextintoblocks{%
+ \.setcounter\.i{0}%
+ \.for \.jz = 1 to \.numshortblocks by 1%
+ {\.stepcounter\.i
+ \.splitoffblock{\.codetext}{\_the\.i}{\.shortblock_size}%
+ }%
+ \_ea\_ifnum\.numlongblocks>0\_relax
+ \.for \.jz = 1 to \.numlongblocks by 1%
+ {\.stepcounter\.i
+ \.splitoffblock{\.codetext}{\_the\.i}{\.longblock_size}%
+ }%
+ \_fi
+}%
+
+\_def\.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{<Splitting off block #2>}%
+ \_ea\_gdef\_csname datablock@#2\_endcsname{}% %This line is important!
+ \.for \.iz = 1 to #3 by 1%
+ {\_edef\.argument{{#2}(#1)}%
+ \_ea\.splitoffblock_int\.argument
+ }%
+}%
+
+\_def\.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.
+ \_ea\_xdef\_csname datablock@#1\_endcsname{\_csname datablock@#1\_endcsname#2#3}%
+ \_xdef\.codetext{#4}%
+}%
+
+\_def\.createerrorblocks{%
+ \.for \.ii = 1 to \.numblocks by 1%
+ {\.message{<Making error block \_the\.ii>}%
+ \.FXgenerate_errorbytes{\_csname datablock@\_the\.ii\_endcsname}{\.numeccodewords}%
+ \_ea\_xdef\_csname errorblock@\_the\.ii\_endcsname{\.FXerrorbytes}%
+ }%
+}%
+
+\_def\.interleave{%
+ \.setcounter\.i{0}%
+ \_def\.interleaved_text{}%
+ \.message{<Interleaving datablocks of length \.shortblock_size\_space and \.longblock_size: }%
+ \.for \.ii = 1 to \.shortblock_size by 1%
+ {\.for \.jj = 1 to \.numblocks by 1%
+ {\.writefromblock{datablock}{\_the\.jj}%
+ }%
+ \.message{\_the\.ii,}%
+ }%
+ %The long blocks are numbered \.numshortblocks+1, \.numshortblocks+2, ..., \.numblocks.
+ \.a=\.numshortblocks\_relax
+ \_advance\.a by 1\_relax
+ \.for \.jj = \.a to \.numblocks by 1%
+ {\.writefromblock{datablock}{\_the\.jj}}%
+ \_ea\_ifnum\.numlongblocks>0\_relax%
+ \.message{\.longblock_size.>}%
+ \_else
+ \.message{.>}%
+ \_fi
+ \.message{<Interleaving errorblocks of length \.numeccodewords: }%
+ \.for \.ii = 1 to \.numeccodewords by 1%
+ {\.message{\_the\.ii,}%
+ \.for \.jj = 1 to \.numblocks by 1%
+ {\.writefromblock{errorblock}{\_the\.jj}%
+ }%
+ }%
+ \.message{.><Interleaving complete.>}%
+}%
+
+\_def\.writefromblock#1#2{%
+ % #1 = either 'datablock' or 'errorblock'
+ % #2 = block number, in {1,...,\.numblocks}%
+ \_edef\.argument{(\_csname #1@#2\_endcsname\_relax\_relax\_relax)}%
+ \_ea\.writefromblock_int\.argument
+ \_ea\_xdef\_csname #1@#2\_endcsname{\.writefromblock_remainder}%
+}%
+
+\_def\.writefromblock_int(#1#2#3){%
+ % #1#2 = first byte (in hex) of text, which will be written to \.interleaved_text
+ % #3 = remainder, including \_relax\_relax\_relax terminator.
+ \.xaddto{\.interleaved_text}{#1#2}%
+ \.writefromblock_intint(#3)%
+}%
+
+\_def\.writefromblock_intint(#1\_relax\_relax\_relax){%
+ \_xdef\.writefromblock_remainder{#1}%
+}%
+
+\_newifi\_ifqr_leadingcoeff
+\_def\.testleadingcoeff(#1#2){%
+ % Tests whether the leading digit of #1#2 is 1.
+ \_ifnum#1=1\_relax
+ \.leadingcoefftrue
+ \_else
+ \.leadingcoefffalse
+ \_fi
+}%
+
+\_def\.polynomialdivide#1#2{%
+ \_edef\.numerator{#1}%
+ \_edef\.denominator{#2}%
+ \.divisiondonefalse%
+ \_ea\_ea\_ea\.oneroundofdivision\_ea\_ea\_ea{\_ea\.numerator\_ea}\_ea{\.denominator}%
+}%
+
+\_def\.empty{}%
+\_def\.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.
+ %
+ \.testleadingcoeff(#1)%
+ \_ifqr_leadingcoeff
+ \.xorbitstrings{#1}{#2}%
+ \_ifqr_xorfailed
+ %If xor failed, that means our #1 was already the remainder!
+ \.divisiondonetrue
+ \_edef\.theremainder{#1}%
+ \_else
+ %xor succeeded. We need to recurse.
+ \_ea\_ea\_ea\_edef\_ea\_ea\_ea\.numerator\_ea\_ea\_ea{\_ea\.stripleadingzero\_ea(\.xorresult)}%
+ \_fi
+ \_else
+ \_ea\_def\_ea\.numerator\_ea{\.stripleadingzero(#1)}%
+ \_ifx\.numerator\.empty
+ \.divisiondonetrue
+ \_def\.theremainder{0}%
+ \_fi
+ \_fi
+ \_ifqr_divisiondone
+ \_relax
+ \_else
+ \_ea\.oneroundofdivision\_ea{\.numerator}{#2}%
+ \_fi
+}%
+
+\_def\.stripleadingzero(0#1){#1}%Strips off a leading zero.
+
+\_newifi\_ifqr_xorfailed% This flag will trigger when #2 is longer than #1.
+
+\_def\.xorbitstrings#1#2{%
+ % #1 = bitstring
+ % #2 = bitstring no longer than #1
+ \.xorfailedfalse
+ \_edef\.argument{(,#1\_relax\_relax)(#2\_relax\_relax)}%
+ \_ea\.xorbitstrings_recursive\.argument
+ %\.xorbitstrings_recursive(,#1\_relax\_relax)(#2\_relax\_relax)%
+}%
+
+\_def\.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\.testii{#2}%
+ \_def\.testiv{#4}%
+ \_ifx\.testii\.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\.testiv\.relax
+ %No problem. We are done.
+ \.xorbit_saveresult(#1#2#3)%
+ \_else
+ %Problem! The second string was longer than the first.
+ \.xorfailedtrue
+ \_def\.xorresult{}%
+ \_fi
+ \_else
+ % There is still a bit to manipulate in #2.
+ % Check whether #4 contains anything.
+ \_ifx\.testiv\.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.
+ \.xorbit_saveresult(#1#2#3)%
+ \_else
+ % Yes, #4 still has something to XOR. Do the task.
+ \_ifnum#2=#4\_relax
+ \.xorbitstrings_recursive(#1%
+ 0,#3)(#5)%
+ \_else
+ \.xorbitstrings_recursive(#1%
+ 1,#3)(#5)%
+ \_fi
+ \_fi
+ \_fi
+}%
+
+\_def\.xorbit_saveresult(#1\_relax\_relax){%
+ %Strips off the extra '\_relax'es at the end.
+ \_def\.xorresult{#1}%
+}%
+
+\_newifi\_ifqr_divisiondone
+
+\_def\.BCHcode#1{%
+ \_edef\.formatinfo{#1}%
+ \_def\.formatinfopadded{\.formatinfo 0000000000}%
+ \_def\.divisor{10100110111}%
+ \.divisiondonefalse
+ \.polynomialdivide{\.formatinfopadded}{\.divisor}%
+ %
+ \.getstringlength{\.theremainder}%
+ %Run loop from stringlength+1 to 10.
+ \.a=\.stringlength\_relax%
+ \_advance\.a by 1\_relax%
+ \.for \.iz = \.a to 10 by 1%
+ {%
+ \_xdef\.theremainder{0\.theremainder}%
+ }%
+ \_edef\.BCHresult{\.formatinfo\.theremainder}%
+}%
+
+\_def\.formatmask{101010000010010}%
+
+\_def\.encodeandmaskformat#1{%
+ \.BCHcode{#1}%
+ \.xorbitstrings{\.BCHresult}{\.formatmask}%
+ \_edef\.formatbitstring{\.xorresult}%
+}%
+
+\_def\.Golaycode#1{%
+ % #1 = 6-bit version number
+ \_edef\.versioninfo{#1}%
+ \_def\.versioninfopadded{\.versioninfo 000000000000}% %Append 12 zeros.
+ \_def\.divisor{1111100100101}%
+ \.divisiondonefalse
+ \.polynomialdivide{\.versioninfopadded}{\.divisor}%
+ %
+ \.getstringlength{\.theremainder}%
+ %Run loop from stringlength+1 to 12.
+ \.a=\.stringlength\_relax%
+ \_advance\.a by 1\_relax%
+ \.for \.iz = \.a to 12 by 1%
+ {%
+ \_xdef\.theremainder{0\.theremainder}%
+ }%
+ \_edef\.Golayresult{\.versioninfo\.theremainder}%
+}%
+\_def\.Fresult{}%
+
+\_def\.xorbitstring#1#2#3{%
+ % #1 = new macro to receive result
+ % #2, #3 = bitstrings to xor. The second can be shorter than the first.
+ \_def\.xor_result{}%
+ \_edef\.argument{(#2\_relax\_relax)(#3\_relax\_relax)}%
+ \_ea\.xorbitstring_recursive\.argument%
+ \_edef#1{\.xor_result}%
+}%
+\_def\.xorbitstring_recursive(#1#2)(#3#4){%
+ \_edef\.testi{#1}%
+ \_ifx\.testi\.relax%
+ %Done.
+ \let\.next=\_relax%
+ \_else
+ \_if#1#3\_relax
+ \.xaddto{\.xor_result}{0}%
+ \_else
+ \.xaddto{\.xor_result}{1}%
+ \_fi
+ \_edef\.next{\_noexpand\.xorbitstring_recursive(#2)(#4)}%
+ \_fi
+ \.next
+}
+
+\_def\.Faddchar_raw#1#2{%
+ %Add two hexadecimal digits using bitwise xor
+ \.hextobinary[4]{\.summandA}{#1}%
+ \.hextobinary[4]{\.summandB}{#2}%
+ \.xorbitstring{\.Fresult}{\.summandA}{\.summandB}%
+ \.binarytohex[1]{\.Fresult}{\.Fresult}%
+}%
+
+\_def\.canceltwos#1{%
+ \_edef\.argument{(#1\_relax\_relax)}%
+ \_ea\.canceltwos_int\.argument%
+}%
+
+\_def\.canceltwos_int(#1#2){%
+ \_ea\.canceltwos_recursion(,#1#2)%
+}%
+
+\_def\.canceltwos_recursion(#1,#2#3){%
+ \_def\.testii{#2}%
+ \_ifx\.testii\.relax
+ %Cancelling complete.
+ \.striptworelaxes(#1#2#3)%
+ %Now \.Fresult contains the answer.
+ \_else
+ \_relax
+ \_ifnum#2=2\_relax
+ \.canceltwos_recursion(#10,#3)%
+ \_else
+ \.canceltwos_recursion(#1#2,#3)%
+ \_fi
+ \_fi
+}%
+
+\_def\.striptworelaxes(#1\_relax\_relax){%
+ \_gdef\.Fresult{#1}%
+}%
+
+\.for \.iz = 0 to 15 by 1%
+ {\.decimaltohex[1]{\.tempa}{\_the\.iz}%
+ \.for \.jz = 0 to 15 by 1%
+ {\.decimaltohex[1]{\.tempb}{\_the\.jz}%
+ \.Faddchar_raw\.tempa\.tempb
+ \_ea\_xdef\_csname F@addchar@\.tempa\.tempb\_endcsname{\.Fresult}%
+ }%
+ }%
+
+\_def\.Faddchar#1#2{%
+ \_ea\_def\_ea\.Fresult\_ea{\_csname F@addchar@#1#2\_endcsname}%
+}%
+
+\_def\.Faddstrings#1#2{%
+ \_edef\.argument{(,#1\_relax\_relax)(#2\_relax\_relax)}%
+ \_ea\.Faddstrings_recursion\.argument%
+}%
+
+\_def\.Faddstrings_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\.testii{#2}%
+ \_def\.testiv{#4}%
+ \_ifx\.testii\.relax
+ %The entire string has been processed.
+ \_gdef\.Fresult{#1}%
+ \_else
+ \_ifx\.testiv\.relax
+ %The second string is over.
+ \.striptworelaxes(#1#2#3)%
+ %Now \.Fresult contains the answer.
+ \_else
+ %We continue to add.
+ \.Faddchar{#2}{#4}%
+ \_edef\.argument{(#1\.Fresult,#3)(#5)}%
+ \_ea\.Faddstrings_recursion\.argument%
+ \_fi
+ \_fi
+}%
+\_gdef\.Fstripleadingzero(0#1){\_edef\.Fresult{#1}}%
+
+\.i=0%
+\_def\.poweroftwo{1}%
+\.for \.iz = 1 to 254 by 1%
+ {\_global\_advance\.i by1%
+ \.a=\.poweroftwo\_relax
+ \_multiply\.a by 2\_relax
+ \_edef\.poweroftwo{\_the\.a}%
+ \.decimaltohex[2]{\.poweroftwo_hex}{\.poweroftwo}%
+ \_ea\_ifnum\.poweroftwo>255\_relax
+ %We need to bitwise add the polynomial represented by 100011101, i.e. 0x11d.
+ \.Faddstrings{\.poweroftwo_hex}{11d}% %Now it should start with 0.
+ \_ea\.Fstripleadingzero\_ea(\.Fresult)% %Now it should be two hex digits.
+ \_edef\.poweroftwo_hex{\.Fresult}% %Save the hex version.
+ \.hextodecimal{\.poweroftwo}{\.Fresult}%
+ \_fi
+ \_xdef\.poweroftwo{\.poweroftwo}%
+ \_ea\_xdef\_csname F@twotothe@\_the\.i\_endcsname{\.poweroftwo_hex}%
+ \_ea\_xdef\_csname F@logtwo@\.poweroftwo_hex\_endcsname{\_the\.i}%
+ }%
+\_ea\_xdef\_csname F@twotothe@0\_endcsname{01}%
+\_ea\_xdef\_csname F@logtwo@01\_endcsname{0}%
+
+\_def\.Ftwotothe#1{%
+ \_ea\_xdef\_ea\.Fresult\_ea{\_csname F@twotothe@#1\_endcsname}%
+}%
+\_def\.Flogtwo#1{%
+ \_ea\_xdef\_ea\.Fresult\_ea{\_csname F@logtwo@#1\_endcsname}%
+}%
+
+\_def\.zerozero{00}%
+
+\_def\.Fmultiply#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 \.Fresult
+ \_edef\.argA{#1}%
+ \_edef\.argB{#2}%
+ \_ifx\.argA\.zerozero
+ \_def\.Fresult{00}%
+ \_else
+ \_ifx\.argB\.zerozero
+ \_def\.Fresult{00}%
+ \_else
+ \_ea\.Flogtwo\_ea{\.argA}%
+ \_edef\.logA{\.Fresult}%
+ \_ea\.Flogtwo\_ea{\.argB}%
+ \_edef\.logB{\.Fresult}%
+ \_ea\.a\_ea=\.logA\_relax% \.a = \logA
+ \_ea\_advance\_ea\.a\.logB\_relax% \advance \.a by \logB
+ \_ifnum\.a>254\_relax%
+ \_advance\.a by -255\_relax
+ \_fi
+ \_ea\.Ftwotothe\_ea{\_the\.a}%
+ % Now \.Fresult contains the product, as desired.
+ \_fi
+ \_fi
+}%
+
+\_newifi\_ifqr_FXleadingcoeff_zero
+\_def\.FXtestleadingcoeff(#1#2#3){%
+ % Tests whether the leading coefficient of the hex-string #1#2#3 is '00'.
+ \_edef\.FXleadingcoefficient{#1#2}%
+ \.FXleadingcoeff_zerofalse
+ \_ifx\.FXleadingcoefficient\.zerozero
+ \.FXleadingcoeff_zerotrue
+ \_fi
+}%
+
+\_newifi\_ifqr_FXdivisiondone
+
+\_newcount\.divisionsremaining %Keep track of how many divisions to go!
+\_def\.FXpolynomialdivide#1#2{%
+ \_edef\.FXnumerator{#1}%
+ \_edef\.denomin{#2}%
+ \.getstringlength\.FXnumerator
+ \.setcounter\.divisionsremaining{\.stringlength}%
+ \.getstringlength\.denomin
+ \.addtocounter\.divisionsremaining{-\.stringlength}%
+ \.addtocounter\.divisionsremaining{2}%
+ \_divide\.divisionsremaining by 2\_relax %2 hex chars per number
+ \.FXdivisiondonefalse
+ \_ea\_ea\_ea\.FXpolynomialdivide_recursive\_ea\_ea\_ea{\_ea\.FXnumerator\_ea}\_ea{\.denomin}%
+}%
+
+\_def\.FXpolynomialdivide_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.
+ %
+ \.FXtestleadingcoeff(#1)%
+ \_ifqr_FXleadingcoeff_zero
+ %Leading coefficient is zero, so remove it.
+ \_ea\_def\_ea\.FXnumerator\_ea{\.FXstripleadingzero(#1)}%
+ \_else%
+ %Leading coefficient is nonzero, and contained in \.FXleadingcoefficient
+ \.FXsubtractphase{#1}{#2}{\.FXleadingcoefficient}%
+ \_ifqr_FXsubtractfailed
+ %If subtraction failed, that means our #1 was already the remainder!
+ \.FXdivisiondonetrue
+ \_edef\.theremainder{#1}%
+ \_else%
+ %xor succeeded. We need to recurse.
+ \_ea\_ea\_ea\_edef\_ea\_ea\_ea\.FXnumerator\_ea\_ea\_ea{\_ea\.FXstripleadingzero\_ea(\.FXsubtraction_result)}%
+ \_fi%
+ \_fi%
+ \.addtocounter\.divisionsremaining{-1}%
+ \_ifnum\.divisionsremaining=0\_relax
+ %Division is done!
+ \.FXdivisiondonetrue
+ \_edef\.theremainder{\.FXnumerator}%
+ \_relax%
+ \_else%
+ \_ea\.FXpolynomialdivide_recursive\_ea{\.FXnumerator}{#2}%
+ \_fi%
+}%
+
+\_def\.FXstripleadingzero(00#1){#1}%Strips off a single leading zero of F_256.
+
+\_newifi\_ifqr_FXsubtractfailed% This flag will trigger when #2 is longer than #1.
+
+\_def\.FXsubtractphase#1#2#3{%
+ % #1 = bitstring
+ % #2 = bitstring no longer than #1
+ % #3 = leading coefficient
+ \.FXsubtractfailedfalse
+ \_edef\.argument{(,#1\_relax\_relax\_relax)(#2\_relax\_relax\_relax)(#3)}%
+ \_ea\.FXsubtract_recursive\.argument%
+}%
+
+\_def\.FXsubtract_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\.testii{#2}%
+ \_def\.testv{#5}%
+ \_ifx\.testii\.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\.testv\.relax
+ %No problem. We are done.
+ \.FXsubtract_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.
+ \.FXsubtractfailedtrue
+ \_def\.FXsubtraction_result{}%
+ \_fi
+ \_else
+ % There is still a coefficient to manipulate in #2#3.
+ % Check whether #5 contains anything.
+ \_ifx\.testv\.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.
+ \.FXsubtract_saveresult(#1#2#3#4)%
+ \_else
+ % Yes, #5#6 still has something to XOR. Do the task.
+ \.Fmultiply{#5#6}{#8}% Multiply by the factor 'a'.
+ \.Faddstrings{#2#3}{\.Fresult}% Subtract. (We're in characteristic two, so adding works.)
+ \_edef\.argument{(#1\.Fresult,#4)(#7)(#8)}%
+ \_ea\.FXsubtract_recursive\.argument%
+ \_fi
+ \_fi
+}%
+
+\_def\.FXsubtract_saveresult(#1\_relax\_relax\_relax){%
+ %Strips off the three extra '\_relax'es at the end.
+ \_def\.FXsubtraction_result{#1}%
+}%
+
+\_def\.FXcreategeneratorpolynomial#1{%
+ % #1 = n, the number of error codewords desired.
+ % We need to create \prod_{j=0}^{n-1} (x-2^j).
+ \_edef\.FXgenerator_degree{#1}%
+ \_def\.FXgeneratorpolynomial{01}% Initially, set it equal to 1.
+ \.setcounter\.i{0}%
+ \.FXcreategenerator_recursive%
+ %The result is now stored in \.FXgeneratorpolynomial
+}%
+
+\_def\.FXcreategenerator_recursive{%
+ % \.FXgeneratorpolynomial 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 \.FXgeneratorpolynomial 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\.summandA{\.FXgeneratorpolynomial 00}% This is f(x) * x
+ \_edef\.summandB{00\.FXgeneratorpolynomial}% This is f(x), with a 0x^{i+1} in front.
+ \.Ftwotothe{\_the\.i}%
+ \_edef\.theconstant{\.Fresult}%
+ \.FXsubtractphase{\.summandA}{\.summandB}{\.theconstant}%
+ %This calculates \.summandA + \.theconstant * \.summandB
+ %and stores the result in \.FXsubtraction_result
+ \_edef\.FXgeneratorpolynomial{\.FXsubtraction_result}%
+ \.stepcounter\.i
+ \_ea \_ifnum\.FXgenerator_degree=\.i\_relax
+ %We just multiplied by (x-2^{n-1}), so we're done.
+ \_relax
+ \_else%
+ %We need to do this again!
+ \_ea \.FXcreategenerator_recursive
+ \_fi
+}%
+
+\_def\.FXgenerate_errorbytes#1#2{%
+ % #1 = datastream in hex
+ % #2 = number of error correction bytes requested
+ \_edef\.numerrorbytes{#2}%
+ \_ea\.FXcreategeneratorpolynomial\_ea{\.numerrorbytes}%
+ \_edef\.FXnumerator{#1}%
+ \.for \.iz = 1 to \.numerrorbytes by 1%
+ {\.xaddto\.FXnumerator{00}}% %One error byte means two hex codes.
+ \.FXpolynomialdivide{\.FXnumerator}{\.FXgeneratorpolynomial}%
+ \_edef\.FXerrorbytes{\.theremainder}%
+}%
+\_newifi\_ifqr_versionmodules
+
+\_def\.level_char#1{%
+ \_ea\_ifcase#1
+ M\_or L\_or H\_or Q\_fi}%
+
+\_newifi\_ifqr_versiongoodenough
+\_def\.choose_bestversion#1{%
+ % \.desiredversion = user-requested version
+ % \.desiredlevel = user-requested error-correction level
+ \_edef\.stringlength{\.utfstringlen{#1}}%
+ %
+ %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\.versiongoodenoughfalse%
+ \_gdef\.bestversion{0}%
+ \_gdef\.bestlevel{0}%
+ \_ifnum\.desiredversion=0\_relax
+ \.a=1\_relax
+ \_else
+ \.a=\.desiredversion\_relax
+ \_fi
+ \.for \.iz=\.a to 40 by 1
+ {\_edef\.version{\_the\.iz}%
+ \_global\.versiongoodenoughfalse
+ \.for \.jz=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.
+ \.a = \.jz\_relax
+ \_divide \.a by 2\_relax
+ \_multiply \.a by 4\_relax
+ \_advance \.a by 1\_relax
+ \_advance \.a by -\.jz\_relax
+ \_edef\.level{\_the\.a}%
+ \_ifnum\.desiredlevel=\.a\_relax
+ \_global\.versiongoodenoughtrue
+ \_fi
+ \_ifqr_versiongoodenough
+ \.calculate_capacity{\.version}{\.level}%
+ \_ea\_ea\_ea\_ifnum\_ea\.truecapacity\_ea<\.stringlength\_relax
+ %Too short
+ \_relax
+ \_else
+ %Long enough!
+ \_xdef\.bestversion{\.version}%
+ \_xdef\.bestlevel{\.level}%
+ \_global\.iz=40%
+ \_fi
+ \_fi
+ }%
+ }%
+ \_edef\.version{\.bestversion}%
+ \_edef\.level{\.bestlevel}%
+ \_ea\_ifnum\.desiredversion>0\_relax
+ \_ifx\.bestversion\.desiredversion\_relax
+ %No change from desired version.
+ \_else
+ %Version was increased
+ \.message{<Requested QR version '\.desiredversion' is too small for desired text.}%
+ \.message{Version increased to '\.bestversion' to fit text.>^^J}%
+ \_fi
+ \_fi
+ \_ifx\.bestlevel\.desiredlevel\_relax
+ %No change in level.
+ \_else
+ \.message{<Error-correction level increased from \.level_char{\.desiredlevel}}%
+ \.message{to \.level_char{\.bestlevel} at no cost.>^^J}%
+ \_fi
+}%
+
+\_def\.calculate_capacity#1#2{%
+ \_edef\.version{#1}%
+ \_edef\.level{#2}%
+ %Calculate \.size, the number of modules per side.
+ % The formula is 4\.version+17.
+ \.a=\.version\_relax
+ \_multiply\.a by 4\_relax
+ \_advance\.a by 17\_relax
+ \_xdef\.size{\_the\.a}%
+ %
+ % Calculate \.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( \.version / 7 ), except that k=0 for version 1.
+ \_ea\_ifnum\.version=1\_relax%
+ \_def\.k{0}%
+ \_else%
+ \.a=\.version\_relax
+ \_divide \.a by 7\_relax
+ \_advance\.a by 2\_relax
+ \_edef\.k{\_the\.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.
+ \.a=\.size\_relax
+ \_multiply\.a by 2\_relax
+ \_advance\.a by 160\_relax
+ \_ea\_ifnum\.k=0\_relax\_else
+ %\.k is nonzero, hence at least 2, so we continue to add 25(k^2-3)-10(k-2).
+ \.b=\.k\_relax
+ \_multiply\.b by \.k\_relax
+ \_advance\.b by -3\_relax
+ \_multiply\.b by 25\_relax
+ \_advance\.a by \.b\_relax
+ \.b=\.k\_relax
+ \_advance\.b by -2\_relax
+ \_multiply\.b by 10\_relax
+ \_advance\.a by -\.b\_relax
+ \_fi
+ \_edef\.numfunctionpatternmodules{\_the\.a}%
+ %
+ %Calculate the number of version modules, either 36 or 0.
+ \_ea\_ifnum\.version>6\_relax
+ \.versionmodulestrue
+ \_def\.numversionmodules{36}%
+ \_else
+ \.versionmodulesfalse
+ \_def\.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 \.numdatacodewords;
+ %the leftover bits are \.numremainderbits.
+ \.a=\.size\_relax
+ \_multiply \.a by \.size\_relax
+ \_advance \.a by -\.numfunctionpatternmodules\_relax
+ \_advance \.a by -31\_relax% % There are 31 format modules.
+ \_advance \.a by -\.numversionmodules\_relax
+ \.b=\.a\_relax
+ \_divide \.a by 8\_relax
+ \_edef\.numdatacodewords{\_the\.a}%
+ \_multiply\.a by 8\_relax
+ \_advance \.b by -\.a\_relax
+ \_edef\.numremainderbits{\_the\.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.
+ \_ea\_ifnum\.version<10\_relax
+ \_def\.charactercountbytes_byte{1}%
+ \_def\.charactercountbits_byte{8}%
+ \_else
+ \_def\.charactercountbytes_byte{2}%
+ \_def\.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 \.totaldatacodewords.
+ % The following macro sets \.numblocks and \.numeccodewords
+ % based on Table 9 of the QR specification.
+ \.settableix
+ \.a = -\.numblocks\_relax
+ \_multiply \.a by \.numeccodewords\_relax
+ \_advance\.a by \.numdatacodewords\_relax
+ \_edef\.totaldatacodewords{\_the\.a}%
+ \_advance\.a by -\.charactercountbytes_byte\_relax%Subtract character count
+ \_advance\.a by -1\_relax% Subtract 1 byte for the 4-bit mode indicator and the 4-bit terminator at the end.
+ \_edef\.truecapacity{\_the\.a}%
+}
+
+\_def\.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 \setversion should be called every time!
+ %
+ \_edef\.version{#1}%
+ \_edef\.level{#2}%
+ %
+ \.calculate_capacity{\.version}{\.level}%
+ %The capacity-check code sets the following:
+ % * \.size
+ % * \.k
+ % * \_ifqr_versionmodules
+ % * \.numversionmodules
+ % * \.numdatacodewords
+ % * \.numremainderbits
+ % * \.charactercountbits_byte
+ % * \.charactercountbytes_byte
+ % * \.numblocks (via \.settableix)
+ % * \.numeccodewords (via \.settableix)
+ % * \.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.
+ %
+ \.a = \.size\_relax
+ \_advance\.a by -13\_relax
+ \_multiply\.a by 2\_relax
+ \.b = \.k\_relax
+ \_advance \.b by -1\_relax
+ \_divide\.a by \.b\_relax
+ \_advance\.a by 3\_relax
+ \_divide\.a by 4\_relax
+ \_multiply\.a by 2\_relax
+ \_edef\.alignment_generalskip{\_the\.a}%
+ %
+ %Now set \.alignment_firstskip to (\.size-13)-(\.k-2)*\.alignment_generalskip %
+ \.a = \.k\_relax
+ \_advance\.a by -2\_relax
+ \_multiply\.a by -\.alignment_generalskip\_relax
+ \_advance\.a by \.size\_relax
+ \_advance\.a by -13\_relax
+ \_edef\.alignment_firstskip{\_the\.a}%
+ %
+ %
+ %
+ % Our \.totaldatacodewords bytes of data are broken up as evenly as possible
+ % into \.numblocks datablocks; some may be one byte longer than others.
+ % We set \.shortblock_size to floor(\.totaldatacodewords / \.numblocks)
+ % and \.numlongblocks to mod(\.totaldatacodewords , \.numblocks).
+ \.a=\.totaldatacodewords\_relax
+ \_divide\.a by \.numblocks\_relax
+ \_edef\.shortblock_size{\_the\.a}%
+ \_multiply\.a by -\.numblocks\_relax
+ \_advance\.a by \.totaldatacodewords\_relax
+ \_edef\.numlongblocks{\_the\.a}%
+ %
+ %Set \.longblock_size to \.shortblock_size+1.
+ \.a=\.shortblock_size\_relax
+ \_advance\.a by 1\_relax
+ \_edef\.longblock_size{\_the\.a}%
+ %
+ %Set \.numshortblocks to \.numblocks - \.numlongblocks
+ \.b=\.numblocks\_relax
+ \_advance\.b by -\.numlongblocks\_relax
+ \_edef\.numshortblocks{\_the\.b}%
+}%
+
+\_def\.settableix_int(#1,#2){%
+ \_edef\.numblocks{#1}%
+ \_edef\.numeccodewords{#2}%
+}%
+
+\_def\.settableix{%
+\_ea\_ifcase\.level\_relax
+ %00: Level 'M', medium error correction
+ \_edef\.tempdata{(%
+ \_ifcase\.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\.tempdata{%
+ (\_ifcase\.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\.tempdata{(%
+ \_ifcase\.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\.tempdata{(%
+ \_ifcase\.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
+\_ea\.settableix_int\.tempdata
+}%
+
+\_def\.qM{M}\_def\.qz{0}%
+\_def\.qL{L}\_def\.qi{1}%
+\_def\.qH{H}\_def\.qii{2}%
+\_def\.qQ{Q}\_def\.qiii{3}%
+\_def\.setlevel#1{%
+ \_edef\.level_selected{#1}%
+ \_ifx\.level_selected\.qM
+ \_edef\.desiredlevel{0}%
+ \_fi
+ \_ifx\.level_selected\.qL
+ \_edef\.desiredlevel{1}%
+ \_fi
+ \_ifx\.level_selected\.qH
+ \_edef\.desiredlevel{2}%
+ \_fi
+ \_ifx\.level_selected\.qQ
+ \_edef\.desiredlevel{3}%
+ \_fi
+ \_ifx\.level_selected\.qz
+ \_edef\.desiredlevel{0}%
+ \_fi
+ \_ifx\.level_selected\.qi
+ \_edef\.desiredlevel{1}%
+ \_fi
+ \_ifx\.level_selected\.qii
+ \_edef\.desiredlevel{2}%
+ \_fi
+ \_ifx\.level_selected\.qiii
+ \_edef\.desiredlevel{3}%
+ \_fi
+}%
+
+% key-value pairs (OPmac trick 0069)
+\_def\.kv#1{\_ifcsname _qr_kv:#1\_endcsname \_csname _qr_kv:#1\_ea\_endcsname
+ \_else \_ea\.kvunknown \_fi
+}
+\_def\.kvunknown{???}
+\_def\.kvscan #1#2=#3,{\_ifx#1,\_else \_sdef{_qr_kv:#1#2}{#3}\_ea\.kvscan\_fi}
+
+\_def\.qrset#1{\_def\.tmpb{#1,}%
+ \_replstring\.tmpb{ =}{=}\_replstring\.tmpb{= }{=}%
+ \_replstring\.tmpb{tight,}{qr-border=0,}%
+ \_replstring\.tmpb{padding,}{qr-border=1,}%
+ \_replstring\.tmpb{verbose,}{qr-message=1,}%
+ \_replstring\.tmpb{silent,}{qr-message=0,}%
+ \_replstring\.tmpb{draft,}{qr-final=0,}%
+ \_replstring\.tmpb{final,}{qr-final=1,}%
+ \_replstring\.tmpb{nolink,}{qr-link=0,}%
+ \_replstring\.tmpb{link,}{qr-link=1,}%
+ \_ea\.kvscan\.tmpb,=,%
+ \.desiredheight=\.kv{height}\_relax
+ \.setlevel{\.kv{level}}%
+ \_edef\.desiredversion{\.kv{version}}%
+}
+\.qrset{height=2cm, version=0, level=M, tight, silent, final, nolink}
+
+\_def\.setcounter #1#2{\_global#1=#2\_relax}
+\_def\.stepcounter #1{\_global\_advance#1 by1\_relax}
+\_def\.addtocounter#1#2{\_global\_advance#1 by#2\_relax}
+
+\_def\.qrcode{\_begingroup
+ \_isnextchar[{\.qrcodeA}{\.qrcodeB}%
+}
+\_def\.qrcodeA[#1]{\.qrset{#1}\_ea\.qrcodeB\_romannumeral-`\.}
+\_def\.qrcodeB#1{%
+ \_if1\.kv{qr-message}\_let\.message=\_message \_else \_def\.message##1{}\_fi
+ \_if1\.kv{qr-border}\_def\.padd{\_kern4\.modulesize}\_else\_def\.padd{}\_fi
+ \_bgroup
+ \_escapechar=-1
+ \_xdef\.etext{\_detokenize{#1}}\_gdef\.text{#1}%
+ \_egroup
+ \.qrcode_int
+ \_endgroup
+}
+\_def\.qrcode_int{%
+ \.message{<QR code requested for "\.etext" in version
+ \.desiredversion-\.level_char{\.desiredlevel}.>^^J}%
+ %First, choose the version and level.
+ %Recall that \.choose_bestversion sets \.version and \.level.
+ \_ea\.choose_bestversion\_ea{\.etext}%
+ \_if1\.kv{qr-final}%
+ \.setversion{\.version}{\.level}%
+ \.qrcode_int_new
+ \_else
+ \.modulesize=\.desiredheight
+ \_divide\.modulesize by \.size\_relax
+ \_let\.d=\.desiredheight
+ \_vbox{\.padd\_hbox{\.padd\_vbox to\.d{\_hrule\_vss
+ \_hbox to\.d{\_vrule height.7\.d depth.3\.d \_hss ...QR...\_hss\_vrule}%
+ \_vss\_hrule}\.padd}\.padd}%
+ \_fi
+}%
+
+\_public \qrcode \qrset ;
+
+\_def\.qrcode_int_new{%
+ \.qrbeginhook
+ \.createsquareblankmatrix{newqr}{\.size}%
+ \.placefinderpatterns{newqr}%
+ \.placetimingpatterns{newqr}%
+ \.placealignmentpatterns{newqr}%
+ \.placedummyformatpatterns{newqr}%
+ \.placedummyversionpatterns{newqr}%
+ \.message{<Calculating QR code for "\.etext" in
+ version \.version-\.level_char{\.level}.>^^J}%
+ \_ea\.encode_binary\_ea{\.etext}%
+ \.splitcodetextintoblocks
+ \.createerrorblocks
+ \.interleave
+ \.message{<Writing data...}%
+ \.writedata_hex{newqr}{\.interleaved_text}%
+ \.message{done.>^^J}%
+ \.writeremainderbits{newqr}%
+ \.chooseandapplybestmask{newqr}%
+ \.decimaltobinary[2]{\.level_binary}{\.level}%
+ \.decimaltobinary[3]{\.mask_binary}{\.mask_selected}%
+ \_edef\.formatstring{\.level_binary\.mask_binary}%
+ \.message{<Encoding and writing format string...}%
+ \_ea\.encodeandmaskformat\_ea{\.formatstring}%
+ \.writeformatstring{newqr}{\.formatbitstring}%
+ \.message{done.>^^J}%
+ \.message{<Encoding and writing version information...}%
+ \.decimaltobinary[6]{\.version_binary}{\.version}%
+ \.Golaycode{\.version_binary}%
+ \.writeversionstring{newqr}{\.Golayresult}%
+ \.message{done.>^^J}%
+ \.message{<Printing QR code...}%
+ \.matrixtobinary{newqr}%
+ \.restore\.data
+ \.message{done.>^^J}%
+ \.qrendhook
+}%
+
+\_def\.matrixtobinary#1{%
+ \_bgroup
+ \_gdef\.data{}%
+ \_def\.black{1}\_let\.blackfixed=\.black \_let\.blackformat=\.black
+ \_def\.white{0}\_let\.whitefixed=\.white \_let\.whiteformat=\.white
+ \.for \.iz = 1 to \.size by 1
+ {\.for \.jz = 1 to \.size by 1
+ {\_xdef\.data{\.data\.matrixentry{#1}{\_the\.iz}{\_the\.jz}}}}%
+ \_xdef\.data{{\.size}{\.data}}%
+ \_egroup
+}
+
+\_def\.restore#1{\_ea\.restoreA#1}
+\_def\.restoreA#1#2{%
+ \.modulesize=\.desiredheight \_divide\.modulesize by#1
+ \_if1\.kv{qr-link}\_setbox0=\_fi
+ \_vbox\_bgroup\.padd \_offinterlineskip \_baselineskip=\.modulesize
+ \.i=0 \.j=0 \_let\.next=\.restoreB
+ \_hbox\_bgroup\.padd \.restoreB #2%
+ \_if1\.kv{qr-link}\.link{\.etext}{\_box0}\_fi
+}
+\_def\.restoreB#1{\_advance \.j by1
+ \_ifx1#1\_vrule height\.modulesize width\.modulesize\_else \_kern\.modulesize\_fi
+ \_ifnum\.size=\.j \_vrule height\.modulesize width 0pt \.padd\_egroup \_advance\.i by1
+ \_ifnum\.size=\.i \.padd\_egroup \_let\.next=\_relax \_else \_hbox\_bgroup\.padd \_fi
+ \_fi \.next
+}
+
+\_def\.qrbeginhook{}
+\_def\.qrendhook{}
+
+\_endcode
+
+This macro file is created for \OpTeX/. It is derived from:
+
+\begtt
+% qrcode.tex
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Petr Olsak <petr@olsak.net> Jul. 2015
+
+% This macro qrcode.tex is (roughly speaking) a copy of qrcode.sty
+% macro by Anders Hendrickson <ahendric@cord.edu>, see
+% http://www.ctan.org/tex-archive/macros/latex/contrib/qrcode
+
+% The main difference between qrcode.sty and qrcode.tex is, that
+% the LaTeX ballast was removed from qrcode.sty by Petr Olsak. The result:
+% The qrcode.tex macro can be used in plain TeX format too.
+\endtt
+
+\secc Usage
+
+Load this macro file by `\load[qrcode]` and then the command
+`\qrcode{<encoded text>}` or `\qrcode[<options>]{<encoded text>}` is ready to use.
+
+The parameter <encoded text> is used as is (without expanding).
+It follows the same rules as in the `\code{<text>}` macro.
+Use these rules if the encoded text includes a \TeX/ sensitive characters.
+
+The characters from all Unicode table are allowed in <encoded text>.
+
+\secc Options
+
+You can use `\qrset{<options>}` for global-like options and
+`\qrcode[<options>]{<encoded text>}` for local options for one QR code.
+The `\qrset{<options>}` is valid within a group (if exists) or in whole
+document.
+
+Options are separated by comma and they are in two types: single
+word or key=value format. Default options are:
+
+\begtt
+\qrset{height=2cm, version=0, level=M, tight, silent, final, nolink}
+\endtt
+
+The options are the same as described in `qrcode.pdf` at
+\url{http://www.ctan.org/tex-archive/macros/latex/contrib/qrcode}.
+In short:
+
+\begitems
+* `height=dimen` ... The height of the QRcode without padding.
+
+* `version=number` ... Number 0 to 40 linearly depends on the density of QRcode.
+ The 0 means that the density is automatically selected.
+
+* `level=letter` ... L, M, Q o H (low, medium, quality, hight) sets the amount
+ of redundancy in the code in order of error recovering.
+
+* `tight` ... Code without margins.
+* `padding` ... 4module blank margins around the code.
+
+* `verbose` ... Information about calculating in terminal and in the log.
+* `silent` ... No information about calculating.
+
+* `final` ... The QR code is calculated and printed.
+* `draft` ... Only empty rectangle in the same size as QR code is printed.
+
+* `nolink` ... The QR code is not active hyperlink.
+* `link` ... The QR code is active hyperlink to <encoded text>.
+
+* `qrborder={R G B}` ... The color of the frame around active hypertext space
+ if link option is set. R G B (red green blue) are decimal
+ numbers from 0 to 1. The frame is visible only in
+ pdf viewers. Default: invisible frame.
+\enditems
+
+
+Example:
+
+\begtt
+\qrset{silent} % ... all codes will be silent in the log and terminal.
+\qrcode [height=3cm, link, padding, qrborder={1 0 0}] {http://petr.olsak.net}
+ % ... 3cm QRcode as hyperlink
+\endtt
+
+Note:
+
+The saving/restoring pre-calculated QRcodes isn't supported by default.
+If you are printing the same QR codes repeatedly, use \setbox/\copy
+technique. For example:
+
+\begtt
+\newbox\mybox
+\setbox\mybox=\hbox{\qrcode{encoded text}}
+\copy\mybox \copy\mybox \copy\mybox etc.
+\endtt
+
+If you have a huge amount of different QR codes, you can use draft/final
+options.
+
+The `\_qr_data` macro is saved after each \qrcode calculation in the format
+`{size}{111101011...001}` where size is the number of columns or rows in QR
+square and second parameter includes size^2 ones or zeros which means black
+or white modules (scanned left to right, top to bottom). Another information
+can be retrieved from `\_qr_text` macro (encoded text before expanding) and
+`\_qr_etext` macro (raw encoded text, each charater is detokeinized).
+The macros `\_qr_data`, `\_qr_text` and `\_qr_etext` are saved globally.
+