diff --git a/src/maxicode.ps.src b/src/maxicode.ps.src index e95a3cb9..91240c85 100644 --- a/src/maxicode.ps.src +++ b/src/maxicode.ps.src @@ -278,6 +278,8 @@ begin /sete charvals 4 get def } ctxdef + /maxlen mode 5 eq {77} {mode 3 le {84} {93} ifelse} ifelse def + encoding (legacy) eq { % Compute numeric runlengths @@ -311,7 +313,7 @@ begin { % loop % Exit when no characters remain latching back to A if necessary i msglen eq { - cset (seta) ne cset (setb) ne and { + cset (seta) ne cset (setb) ne and out length maxlen lt and { la cset load enc /cset (seta) def } if @@ -497,13 +499,13 @@ begin {32768 lt {4} {5} ifelse} ifelse} def % Operations that don't fit directly into the list below - /enc_eci1 {c neg 1000000 sub } def % Extended - /enc_eci2 {c neg 1000000 sub dup -6 bitshift 32 or exch 63 and} def % Channel - /enc_eci3 {c neg 1000000 sub dup -12 bitshift 48 or exch % Interpretation - dup -6 bitshift 63 and exch 63 and} def - /enc_eci4 {c neg 1000000 sub dup -18 bitshift 56 or exch + /enc_eci {c neg 1000000 sub dup 32 ge {dup 1024 lt { + dup -6 bitshift 32 or exch 63 and} {dup 32768 lt { + dup -12 bitshift 48 or exch + dup -6 bitshift 63 and exch 63 and} { + dup -18 bitshift 56 or exch dup -12 bitshift 63 and exch - dup -6 bitshift 63 and exch 63 and} def + dup -6 bitshift 63 and exch 63 and} ifelse} ifelse} if} def /enc_ns {0 msg n 9 getinterval {48 sub exch 10 mul add} forall % Numeric dup -24 bitshift exch % Sequence dup -18 bitshift 63 and exch @@ -514,24 +516,21 @@ begin seta msg n 2 add get get} def % Shift 3 A % Table of operations - operating table? - /op_tab [ % predicate applicable sets encoding - << /can {2 eci eq } /intake 1 /output 2 /sets 2#11111 /enc {27 enc_eci1 } >> % ECI1 ABCDE - << /can {3 eci eq } /intake 1 /output 3 /sets 2#11111 /enc {27 enc_eci2 } >> % ECI2 ABCDE - << /can {4 eci eq } /intake 1 /output 4 /sets 2#11111 /enc {27 enc_eci3 } >> % ECI3 ABCDE - << /can {5 eci eq } /intake 1 /output 5 /sets 2#11111 /enc {27 enc_eci4 } >> % ECI4 ABCDE - << /can {digits 9 ge } /intake 9 /output 6 /sets 2#11111 /enc {31 enc_ns } >> % NS ABCDE - << /can {seta c known} /intake 1 /output 1 /sets 2#00001 /enc { seta c get} >> % A A - << /can {setb c known} /intake 1 /output 1 /sets 2#00010 /enc { setb c get} >> % B B - << /can {setc c known} /intake 1 /output 1 /sets 2#00100 /enc { setc c get} >> % C C - << /can {setd c known} /intake 1 /output 1 /sets 2#01000 /enc { setd c get} >> % D D - << /can {sete c known} /intake 1 /output 1 /sets 2#10000 /enc { sete c get} >> % E E - << /can {num_a 1 ge } /intake 1 /output 2 /sets 2#00010 /enc {59 seta c get} >> % SHA B - << /can {num_a 2 ge } /intake 2 /output 3 /sets 2#00010 /enc {56 enc_sha2 } >> % SHA2 B - << /can {num_a 3 ge } /intake 3 /output 4 /sets 2#00010 /enc {57 enc_sha3 } >> % SHA3 B - << /can {setb c known} /intake 1 /output 2 /sets 2#00001 /enc {59 setb c get} >> % SHB A - << /can {setc c known} /intake 1 /output 2 /sets 2#11011 /enc {60 setc c get} >> % SHC ABCDE - << /can {setd c known} /intake 1 /output 2 /sets 2#10111 /enc {61 setd c get} >> % SHD ABCDE - << /can {sete c known} /intake 1 /output 2 /sets 2#01111 /enc {62 sete c get} >> % SHE ABCDE + /op_tab [ % predicate applicable sets encoding + << /can {eci 1 ge } /intake 1 /output {out_eci} /sets 2#11111 /enc {27 enc_eci } >> % ECI ABCDE + << /can {digits 9 ge } /intake 9 /output {6 } /sets 2#11111 /enc {31 enc_ns } >> % NS ABCDE + << /can {seta c known} /intake 1 /output {1 } /sets 2#00001 /enc { seta c get} >> % A A + << /can {setb c known} /intake 1 /output {1 } /sets 2#00010 /enc { setb c get} >> % B B + << /can {setc c known} /intake 1 /output {1 } /sets 2#00100 /enc { setc c get} >> % C C + << /can {setd c known} /intake 1 /output {1 } /sets 2#01000 /enc { setd c get} >> % D D + << /can {sete c known} /intake 1 /output {1 } /sets 2#10000 /enc { sete c get} >> % E E + << /can {num_a 1 ge } /intake 1 /output {2 } /sets 2#00010 /enc {59 seta c get} >> % SHA B + << /can {num_a 2 ge } /intake 2 /output {3 } /sets 2#00010 /enc {56 enc_sha2 } >> % SHA2 B + << /can {num_a 3 ge } /intake 3 /output {4 } /sets 2#00010 /enc {57 enc_sha3 } >> % SHA3 B + << /can {setb c known} /intake 1 /output {2 } /sets 2#00001 /enc {59 setb c get} >> % SHB A + << /can {setc c known} /intake 1 /output {2 } /sets 2#11011 /enc {60 setc c get} >> % SHC ABCDE + << /can {setd c known} /intake 1 /output {2 } /sets 2#10111 /enc {61 setd c get} >> % SHD ABCDE + << /can {sete c known} /intake 1 /output {2 } /sets 2#01111 /enc {62 sete c get} >> % SHE ABCDE ] def % Add idx to each entry @@ -543,23 +542,22 @@ begin % Get the shortest encoded length for the code set (state) and plot the path /get_best_length { /latch_length_s latch_length state get def % Get latch length row targetting the code set - max_int /op op_tab 0 get def /org 0 def % Values used if this is not a viable code set + max_int % Length returned if this is not a viable code set code_set_operations state get { % Loop over operations that apply to this code set - /op_ exch def op_ /can get exec { % Execute predicate to see if the operation applies to input - /m n op_ /intake get sub 15 and def % Use intake to index back into circular history buffers - /org_ best_origin m get state get def % Get the best prior code set - best_length m get org_ get % Get the corresponding length of encoding - latch_length_s org_ get add % Add latch length - op_ /output get add % Add output length to yield resulting length - 2 copy gt { - exch /op op_ def /org org_ def % Pick the shortest length and make a note of it + /op exch def % + op /can get exec { % Determine if the operation accepts the input + /m n op /intake get sub 15 and def % Get index into circular history buffers + /org best_origin m get state get def % Get the best prior code set + best_length m get org get % Get the corresponding encoding length + latch_length_s org get add % Add latch length + op /output get exec add % Add output length to yield resulting length + 2 copy gt { % Compare lengths + exch % Keep the shorter length + path_op_0 state op /idx get put % Store operation in path + prior_code_set_0 state org put % Store prior set in path } if pop % Pop off the longer (or equal) length } if } forall - - % Plot the path - prior_code_set_0 state org put - path_op_0 state op /idx get put } def % Unrolled loop to get the best prior code set using a row of @@ -601,8 +599,7 @@ begin % Get the best code set to end with. Code sets with a pad code are first pick /priority [0 1 4 2 3] def - priority 0 get dup best_length_0 exch get - priority 1 4 getinterval {dup best_length_0 exch get dup 3 index lt {4 2 roll} if pop pop} forall + 0 max_int priority {dup best_length_0 exch get dup 3 index lt {4 2 roll} if pop pop} forall /j exch def /state exch def @@ -610,13 +607,8 @@ begin /pad_code [33 33 0 0 28] def /final_code_set pad_code state get 0 eq {0} {state} ifelse def - % Insert a latch to A if the code set does not have a pad code. - % There is something about this that doesn't seem right. - % To paraphrase the standard: - % If the message codewords exactly fill out all the message - % regions of the symbol then the latch to A would be unnecessary - % and would in fact overflow the buffer and cause an error. - pad_code state get 0 eq {j 1 add array dup j 58 put} {j array} ifelse + % Insert a latch to A if padding is necessary and the code set does not have a pad code. + pad_code state get 0 eq j maxlen lt and {j 1 add array dup j 58 put} {j array} ifelse /padval pad_code final_code_set get def /len j def