Skip to content

Commit 06a78b7

Browse files
committed
qrcode: Materialise each mode segment once when the mode changes
The mode sequence derivation extended the pending segment's data array per character, rebuilding it via aload each time the character class run breaks without a mode change - quadratic whenever a long segment accumulates single-character steps, as byte mode does over mixed-case text and URLs. Every segment is a contiguous slice of the message, so track only its start position and take a single getinterval when the mode changes or the message ends.
1 parent 1780b0f commit 06a78b7

2 files changed

Lines changed: 22 additions & 15 deletions

File tree

CHANGES

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
XXXX-XX-XX
2+
3+
* The performance of the QR Code encoder was improved for data that mixes character classes, such as mixed-case text and URLs, by materialising each mode segment once when the mode changes rather than extending it character by character.
4+
5+
16
2026-07-06
27

38
* The performance of the DotCode encoder was improved by sharing a single codeword placement walk between the mask candidates, by deriving each candidate's error correction codewords from those of the unmasked message, and by scoring each candidate together with its lit-edge variant in a single evaluation pass.

src/qrcode.ps.src

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ begin
10801080
%
10811081
% Derive optimal sequence using stack-based accumulation
10821082
%
1083-
/mode -1 def /seqok true def mark /i 0 def {
1083+
/mode -1 def /seqok true def /i 0 def /segstart -1 def mark {
10841084
i msglen ge {exit} if
10851085
/numK numKs i get def
10861086
/numB numBs i get def
@@ -1160,23 +1160,25 @@ begin
11601160
} if
11611161
} loop
11621162
dup //qrcode.K eq fnc1first and {pop //qrcode.B} if % No kanji with fnc1first
1163-
dup mode eq { % Same mode encode directly - extend data on stack
1163+
dup mode eq { % Same mode - grow the pending segment, deferring extraction
11641164
pop
1165-
/dat msg i mode //qrcode.K eq {2} {1} ifelse getinterval def
1166-
[ exch aload pop dat aload pop ] % Extend top data array with dat
1167-
} { % Change mode - push mode and data to stack
1168-
/mode exch def
1169-
mode //qrcode.K eq {//qrcode.K msg i numK 2 mul getinterval} if
1170-
mode //qrcode.B eq {//qrcode.B msg i numB getinterval} if
1171-
mode //qrcode.A eq {//qrcode.A msg i numA getinterval} if
1172-
mode //qrcode.N eq {//qrcode.N msg i numN getinterval} if
1173-
mode //qrcode.E eq {//qrcode.E msg i 1 getinterval /mode -1 def} if
1174-
/dat 1 index def % Copy data to dat variable (sw and data stay on stack)
1165+
/i i mode //qrcode.K eq {2} {1} ifelse add def
1166+
} { % Change mode - materialise the pending segment beneath the new mode, then start a new one
1167+
segstart 0 ge {msg segstart i segstart sub getinterval exch} if
1168+
dup /mode exch def
1169+
/segstart i def
1170+
mode //qrcode.K eq {/i i numK 2 mul add def} if
1171+
mode //qrcode.B eq {/i i numB add def} if
1172+
mode //qrcode.A eq {/i i numA add def} if
1173+
mode //qrcode.N eq {/i i numN add def} if
1174+
mode //qrcode.E eq {/i i 1 add def /mode -1 def} if
11751175
} ifelse
1176-
/i i dat length add def
11771176
} loop
1178-
% Build seq from stack (or set to -1 if invalid)
1179-
seqok {counttomark array astore exch pop} {cleartomark -1} ifelse /seq exch def
1177+
% Build seq from stack, materialising the final pending segment (or set to -1 if invalid)
1178+
seqok {
1179+
segstart 0 ge {msg segstart i segstart sub getinterval} if
1180+
counttomark array astore exch pop
1181+
} {cleartomark -1} ifelse /seq exch def
11801182

11811183
%
11821184
% Encode the sequence

0 commit comments

Comments
 (0)