@@ -541,31 +541,31 @@ begin
541541/qrcode.modeANbeforeE [ 7 8 9 e 3 4 5 4 5 5 5 5 5 5 5 5 6 4 5 5 5 6 6 5 5 5 5 6 6 5 5 6 6 6 5 6 6 6 6 ] readonly def
542542
543543%
544- % Mask functions for each symbol format
544+ % Mask functions
545545%
546- /qrcode.formatmaskfuncs <<
547- (full) [
548- {add 2 mod} bind
549- {exch pop 2 mod} bind
550- {pop 3 mod} bind
551- { add 3 mod} bind
552- {2 idiv exch 3 idiv add 2 mod} bind
553- {mul dup 2 mod exch 3 mod add} bind
554- {mul dup 2 mod exch 3 mod add 2 mod} bind
555- {2 copy mul 3 mod 3 1 roll add 2 mod add 2 mod} bind
556- ]
557- (micro) [
558- {exch pop 2 mod} bind
559- {2 idiv exch 3 idiv add 2 mod} bind
560- {mul dup 2 mod exch 3 mod add 2 mod} bind
561- {2 copy mul 3 mod 3 1 roll add 2 mod add 2 mod} bind
562- ]
563- (rmqr) [
564- {2 idiv exch 3 idiv add 2 mod} bind
565- ]
546+ /qrcode.maskfuncs [
547+ {add 2 mod} bind % 0: (i+j) % 2
548+ {exch pop 2 mod} bind % 1: j % 2
549+ {pop 3 mod} bind % 2: i % 3
550+ {add 3 mod} bind % 3: (i+j) % 3
551+ {2 idiv exch 3 idiv add 2 mod} bind % 4: (j/2 + i/3) % 2
552+ {mul dup 2 mod exch 3 mod add} bind % 5: (i*j) % 2 + (i*j) % 3
553+ {mul dup 2 mod exch 3 mod add 2 mod } bind % 6: ((i*j) % 2 + (i*j) % 3) % 2
554+ {2 copy mul 3 mod 3 1 roll add 2 mod add 2 mod} bind % 7: ((i*j) % 3 + (i+j) % 2) % 2
555+ ] readonly def
556+
557+ %
558+ % Mask bit positions in funcpatlayers for each format
559+ %
560+ % Entries relate to the numbered mask functions above.
561+ %
562+ /qrcode.formatmaskbits <<
563+ (full) [ 0 1 2 3 4 5 6 7 ]
564+ (micro) [ 1 4 6 7 ]
565+ (rmqr) [ 4 ]
566566>> readonly def
567567
568- /qrcode.latevars dup 3 dict def load /init {
568+ /qrcode.latevars dup 4 dict def load /init {
569569
570570 currentglobal
571571 true setglobal
@@ -587,6 +587,25 @@ begin
587587 1 1 255 {dup rsalog exch get exch rslog 3 1 roll put} for
588588 /rslog rslog readonly def
589589
590+ %
591+ % The mask functions have 6x12 periodicity, so we compute an 8-layer array
592+ % representing all mask function patterns at bit positions
593+ %
594+ /funcpatlayers 6 12 mul array def
595+ 0 1 11 {
596+ /j exch def
597+ 0 1 5 {
598+ /i exch def
599+ /bits 0 def
600+ 0 1 7 {
601+ /m exch def
602+ i j //qrcode.maskfuncs m get exec 0 eq { /bits bits 1 m bitshift or def } if
603+ } for
604+ funcpatlayers j 6 mul i add bits put
605+ } for
606+ } for
607+ /funcpatlayers funcpatlayers readonly def
608+
590609 /init { //qrcode.latevars {def} forall } def
591610
592611 end
@@ -624,7 +643,9 @@ begin
624643 /bwipp.qrcodeEmptyData (The data must not be empty) //raiseerror exec
625644 } if
626645
646+ %
627647 % If version is supplied and format is not given then set format to correspond
648+ %
628649 version (unset) ne {
629650 format (unset) eq {
630651 (full)
@@ -644,7 +665,9 @@ begin
644665 /bwipp.qrcodeRMQRwithoutVersion (A version must be provided for RMQR) //raiseerror exec
645666 } if
646667
668+ %
647669 % Default error correction level
670+ %
648671 eclevel (unset) eq {/eclevel format (micro) ne {(M)} {(L)} ifelse def} if
649672
650673 eclevel (L) ne eclevel (M) ne eclevel (Q) ne eclevel (H) ne and and and {
@@ -661,7 +684,9 @@ begin
661684 } if
662685 } if
663686
687+ %
664688 % Parse the input
689+ %
665690 /fncvals <<
666691 /parse parse
667692 /parsefnc parsefnc
@@ -671,7 +696,9 @@ begin
671696 /msg barcode fncvals //parseinput exec def
672697 /msglen msg length def
673698
699+ %
674700 % If FNC1 in first position then escape % as %%
701+ %
675702 /fnc1first false def
676703 msglen 0 gt {
677704 msg 0 get //qrcode.fn1 eq {
@@ -681,7 +708,9 @@ begin
681708 } if
682709 } if
683710
711+ %
684712 % Encoding functions
713+ %
685714 /tobin {
686715 string dup length 1 sub 0 exch 1 exch {1 index exch 48 put} for
687716 dup 3 -1 roll 2 2 index length string cvrs dup length 2 index length exch sub exch putinterval
@@ -1406,31 +1435,37 @@ begin
14061435 } if
14071436
14081437 %
1409- % Calculate the mask patterns
1438+ % Lookup the mask bits corresponding to the mask functions applicable to
1439+ % this format
14101440 %
1411- /maskfuncs //qrcode.formatmaskfuncs format get def
1412- mask -1 ne { % User specifies a mask
1413- /maskfuncs [maskfuncs mask 1 sub get] def
1441+ mask -1 eq {
1442+ /maskbits //qrcode.formatmaskbits format get def
1443+ } { % Just the indicated function when given a user-specified mask
1444+ /maskbits [ //qrcode.formatmaskbits format get mask 1 sub get ] def
14141445 /bestmaskval mask 1 sub def
1415- } if
1416- /masks maskfuncs length array def
1417- 0 1 masks length 1 sub {
1418- /m exch def
1419- /mask rows cols mul array def
1420- 0 1 rows 1 sub {
1421- /j exch def
1422- 0 1 cols 1 sub {
1423- /i exch def
1424- i j maskfuncs m get exec 0 eq
1425- pixs i j qmv get -1 eq and {1} {0} ifelse
1426- mask i j qmv 3 -1 roll put
1427- } for
1446+ } ifelse
1447+ /nmasks maskbits length def
1448+
1449+ %
1450+ % Build masklayers from the extruded funcpatlayers, with function cell
1451+ % values included (as 0 or 255)
1452+ %
1453+ /masklayers rows cols mul array def
1454+ 0 1 rows 1 sub {
1455+ /j exch def
1456+ 0 1 cols 1 sub {
1457+ /i exch def
1458+ /pos i j qmv def
1459+ masklayers pos pixs pos get dup -1 eq {
1460+ pop funcpatlayers j 6 mul 72 mod i 6 mod add get
1461+ } {
1462+ 255 mul
1463+ } ifelse put
14281464 } for
1429- masks m mask put
14301465 } for
14311466
14321467 %
1433- % Walk the symbol placing the bitstream
1468+ % Walk the symbol placing the bitstream by merging it into masklayers
14341469 %
14351470 /posx cols format (rmqr) ne {1} {2} ifelse sub def
14361471 /posy rows 1 sub def
@@ -1439,9 +1474,10 @@ begin
14391474 /num 0 def
14401475 { % loop
14411476 posx 0 lt {exit} if
1442- pixs posx posy qmv get -1 eq {
1443- cws num 8 idiv get 7 num 8 mod sub neg bitshift 1 and
1444- pixs posx posy qmv 3 -1 roll put
1477+ /pos posx posy qmv def
1478+ pixs pos get -1 eq {
1479+ /bit cws num 8 idiv get 7 num 8 mod sub neg bitshift 1 and def
1480+ masklayers pos masklayers pos get bit 255 mul xor put
14451481 /num num 1 add def
14461482 } if
14471483 col 1 eq {
@@ -1565,17 +1601,19 @@ begin
15651601 } def
15661602
15671603 %
1568- % Evaluate the masked symbols to find the most suitable
1604+ % Extract each masked symbol from the required set and evaluate them to
1605+ % find the most suitable
15691606 %
15701607 /bestscore 999999999 def
1571- 0 1 masks length 1 sub {
1608+ 0 1 nmasks 1 sub {
15721609 /m exch def
1610+ /maskbit maskbits m get def
15731611 /masksym rows cols mul array def
15741612 0 1 rows cols mul 1 sub {
15751613 /i exch def
1576- masksym i pixs i get masks m get i get xor put
1614+ masksym i masklayers i get maskbit neg bitshift 1 and put
15771615 } for
1578- masks length 1 ne { % Not rMQR nor user-specified mask
1616+ nmasks 1 ne { % Not rMQR nor user-specified mask
15791617 /score masksym format (full) eq {evalfull} {evalmicro} ifelse def
15801618 score bestscore lt {
15811619 /bestsym masksym def
@@ -1584,6 +1622,7 @@ begin
15841622 } if
15851623 } {
15861624 /bestsym masksym def
1625+ % Note: bestmaskval never set for rMQR, but is not required
15871626 } ifelse
15881627 } for
15891628 /pixs bestsym def
0 commit comments