@@ -775,32 +775,47 @@ begin
775775 /in exch def
776776
777777 %
778- % Each char adds 1 codeword, latches add up to 2
778+ % Codeword sequences are held as persistent chains of segments.
779+ % Each chain head is null or a node [parent_node, segment_array];
780+ % the final sequence is materialised once by walking the chain.
779781 %
780- /maxseqlen in length 3 mul 4 add def
781-
782- /seq0 [ 4 { maxseqlen array } repeat ] def
783- /seq1 [ 4 { maxseqlen array } repeat ] def
784- /len0 4 array def len0 0 0 put len0 1 0 put len0 2 0 put len0 3 0 put
785- /len1 4 array def
786-
787- /curseq seq0 def /curseqlen len0 def
788- /nxtseq seq1 def /nxtseqlen len1 def
782+ /curseqhd [ //pdf417.textsubmodes length { null } repeat ] def
783+ /nxtseqhd [ //pdf417.textsubmodes length { null } repeat ] def
784+ /curseqlen [ //pdf417.textsubmodes length { 0 } repeat ] def
785+ /nxtseqlen [ //pdf417.textsubmodes length { 0 } repeat ] def
789786
790787 /curlen [ //pdf417.e //pdf417.e //pdf417.e //pdf417.e ] def
791788 curlen submode 0 put
792789
793790 %
794- % Derive the optimal sequences ending in each submode
791+ % Flatten a chain of [parent, segment] cons cells of total length L
792+ % into a fresh array. The chain's deepest node holds the prefix, so
793+ % we walk head-to-root and write each segment into the tail of the
794+ % output, advancing pos backwards.
795795 %
796+ /flatten { % hd len -> array
797+
798+ dup array 3 1 roll % pos = len; out = array(len)
799+
800+ { % out hd pos
801+ 1 index null eq { exit } if % done when hd is null
802+ 1 index 1 get % ... seg = hd[1]
803+ exch 1 index length sub % ... pos -= length(seg)
804+ 3 index 1 index 3 index putinterval % out[pos..] = seg
805+ exch pop % drop seg
806+ exch 0 get exch % hd = hd[0]
807+ } loop
808+
809+ pop pop % return out
810+
811+ } def
812+
796813 in {
797814
798815 /char exch def
799816
800- %
801- % Check for optimisations in the current sequences by latching from x to y
802- %
803- { % loop
817+ % Phase 1: relax curlen[*] via the static latch graph
818+ {
804819 /imp false def
805820 //pdf417.textsubmodes {
806821 /x exch def
@@ -809,67 +824,52 @@ begin
809824 /cost curlen x get //pdf417.latlen x get y get add def
810825 cost curlen y get lt {
811826 curlen y cost put
812- % Copy curseq[x] to curseq[y] and append latseq codes
813- /srclen curseqlen x get def
814- srclen 0 gt {
815- curseq y get 0 curseq x get 0 srclen getinterval putinterval
816- } if
817- //pdf417.latseq x get y get {
818- curseq y get srclen 3 -1 roll put
819- /srclen srclen 1 add def
820- } forall
821- curseqlen y srclen put
827+ /latyseg //pdf417.latseq x get y get def
828+ curseqhd y
829+ latyseg length 0 eq
830+ { curseqhd x get }
831+ { [ curseqhd x get latyseg ] }
832+ ifelse
833+ put
834+ curseqlen y curseqlen x get latyseg length add put
822835 /imp true def
823836 } if
824837 } forall
825838 } forall
826- imp not {exit} if % Repeat unless no improvement
839+ imp not {exit} if
827840 } loop
828841
829- %
830- % Determine optimal next sequences for each valid encoding
831- %
832842 /nxtlen [ //pdf417.e //pdf417.e //pdf417.e //pdf417.e ] def
833- nxtseqlen 0 0 put nxtseqlen 1 0 put nxtseqlen 2 0 put nxtseqlen 3 0 put
843+ //pdf417.textsubmodes { nxtseqhd exch null put } forall
844+ //pdf417.textsubmodes { nxtseqlen exch 0 put } forall
834845
835846 //pdf417.textsubmodes {
836847 /x exch def
837848
838- { % loop for common exit
849+ { % loop for common exit
839850
840851 charvals x get char known not {exit} if
841852
842- %
843- % Extend directly: copy curseq[x] + char to nxtseq[x]
844- %
853+ % Phase 2: nxtseq[x] := curseq[x] + [char]
845854 /cost curlen x get 1 add def
846855 cost nxtlen x get lt {
847856 nxtlen x cost put
848- /srclen curseqlen x get def
849- srclen 0 gt {
850- nxtseq x get 0 curseq x get 0 srclen getinterval putinterval
851- } if
852- nxtseq x get srclen char put
853- nxtseqlen x srclen 1 add put
857+ nxtseqhd x [ curseqhd x get [ char ] ] put
858+ nxtseqlen x curseqlen x get 1 add put
854859 } if
855860
856- %
857- % Optimise for direct shifts from y to x
858- %
861+ % Phase 3: shift y -> x for one char (y != x; stays in y)
859862 //pdf417.textsubmodes {
860863 /y exch def
861864 x y ne {
862865 /cost curlen y get //pdf417.shftlen y get x get add 1 add def
863866 cost nxtlen y get lt {
864867 nxtlen y cost put
865- % Copy curseq[y] + shift + char to nxtseq[y]
866- /srclen curseqlen y get def
867- srclen 0 gt {
868- nxtseq y get 0 curseq y get 0 srclen getinterval putinterval
869- } if
870- nxtseq y get srclen x //pdf417.a eq {//pdf417.as} {//pdf417.ps} ifelse put
871- nxtseq y get srclen 1 add char put
872- nxtseqlen y srclen 2 add put
868+ nxtseqhd y [
869+ curseqhd y get
870+ [ x //pdf417.a eq {//pdf417.as} {//pdf417.ps} ifelse char ]
871+ ] put
872+ nxtseqlen y curseqlen y get 2 add put
873873 } if
874874 } if
875875 } forall
@@ -880,23 +880,26 @@ begin
880880 } forall
881881
882882 /curlen nxtlen def
883- % Swap cur and nxt buffers
884- curseq nxtseq /curseq exch def /nxtseq exch def
885- curseqlen nxtseqlen /curseqlen exch def /nxtseqlen exch def
883+ curseqhd nxtseqhd /curseqhd exch def /nxtseqhd exch def
884+ curseqlen nxtseqlen /curseqlen exch def /nxtseqlen exch def
886885
887886 } forall
888887
889888 %
890889 % Select the optimal sequence
891890 %
892891 /minseq //pdf417.e def
892+ /bestsm -1 def
893893 //pdf417.textsubmodes {
894894 /k exch def
895895 curlen k get minseq lt {
896896 /minseq curlen k get def
897- /txtseq curseq k get 0 curseqlen k get getinterval def
897+ /bestsm k def
898898 } if
899899 } forall
900+ bestsm -1 ne {
901+ /txtseq curseqhd bestsm get curseqlen bestsm get flatten def
902+ } if
900903
901904 %
902905 % Encode the sequence
0 commit comments