source: trunk/Packages/lazbarcodes/src/lbc_auspost.pas

Last change on this file was 123, checked in by chronos, 3 years ago
  • Added: QR code image visible in contact others tab. It can be saved as image to file.
File size: 6.4 KB
Line 
1{ lbc_auspost.pas - Handles Australian post barcodes.
2
3 Based on Zint (done by Robin Stuart and the Zint team)
4 http://github.com/zint/zint
5 and Pascal adaption by TheUnknownOnes
6 http://theunknownones.net
7
8 Refactoring: W. Pamler
9}
10
11unit lbc_auspost;
12
13{$IFDEF FPC}
14 {$mode objfpc}{$H+}
15{$ENDIF}
16
17interface
18
19uses
20 Types, SysUtils, zint;
21
22function australia_post(ASymbol: PZintSymbol; ASource: String): Integer;
23
24implementation
25
26uses
27 lbc_reedsolomon, lbc_helper;
28
29const
30 GDSET: String = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #';
31
32 AusNTable: array[0..9] of String = (
33 '00', '01', '02', '10', '11', '12', '20', '21', '22', '30'
34 );
35
36 AusCTable: array[0..63] of String = (
37 '222', '300', '301', '302', '310', '311', '312', '320', '321', '322',
38 '000', '001', '002', '010', '011', '012', '020', '021', '022', '100',
39 '101', '102', '110', '111', '112', '120', '121', '122', '200', '201',
40 '202', '210', '211', '212', '220', '221', '023', '030', '031', '032',
41 '033', '103', '113', '123', '130', '131', '132', '133', '203', '213',
42 '223', '230', '231', '232', '233', '303', '313', '323', '330', '331',
43 '332', '333', '003', '013'
44 );
45
46 AusBarTable: array[0..63] of String = (
47 '000', '001', '002', '003', '010', '011', '012', '013', '020', '021',
48 '022', '023', '030', '031', '032', '033', '100', '101', '102', '103',
49 '110', '111', '112', '113', '120', '121', '122', '123', '130', '131',
50 '132', '133', '200', '201', '202', '203', '210', '211', '212', '213',
51 '220', '221', '222', '223', '230', '231', '232', '233', '300', '301',
52 '302', '303', '310', '311', '312', '313', '320', '321', '322', '323',
53 '330', '331', '332', '333'
54 );
55
56function convert_pattern(data: Char; shift: Integer): Byte; inline;
57begin
58 Result := (Ord(data) - Ord('0')) shl shift;
59end;
60
61{ Adds Reed-Solomon error correction to auspost }
62procedure rs_error_correction(var data_pattern: String);
63var
64 i, triple_writer: Integer;
65 triple: TByteDynArray = nil;
66 inv_triple: TByteDynArray = nil;
67 res : TByteDynArray = nil;
68begin
69 triple_writer := 0;
70 SetLength(triple, 31);
71 SetLength(inv_triple, 31);
72 SetLength(res, 5);
73
74 i := 3;
75 while i <= Length(data_pattern) do
76 begin
77 triple[triple_writer] :=
78 convert_pattern(data_pattern[i ], 4) +
79 convert_pattern(data_pattern[i + 1], 2) +
80 convert_pattern(data_pattern[i + 2], 0);
81 Inc(i, 3);
82 Inc(triple_writer);
83 end;
84
85 for i := 0 to triple_writer - 1 do
86 inv_triple[i] := triple[(triple_writer - 1) - i];
87
88 rs_init_gf($43);
89 rs_init_code(4, 1);
90 rs_encode(triple_writer, @inv_triple[0], @res[0]);
91 for i := 3 downto 0 do
92 data_pattern := data_pattern + AusBarTable[res[i]];
93 rs_free();
94end;
95
96{ Handles Australia Posts's 4 State Codes }
97function australia_post(ASymbol: PZintSymbol; ASource: String): Integer;
98{ Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically
99 (i.e. the FCC doesn't need to be specified by the user) dependent
100 on the length of the input string }
101
102{ The contents of data_pattern conform to the following standard:
103 0 := Tracker, Ascender and Descender
104 1 := Tracker and Ascender
105 2 := Tracker and Descender
106 3 := Tracker only }
107var
108 i, len, writer: Integer;
109 data_pattern: String;
110 fcc: String;
111 dpid: String;
112 localstr: String;
113begin
114 Result := 0;
115 localstr := ASource;
116
117 // Do all of the _length checking first to avoid stack smashing
118 if (ASymbol^.symbology = BARCODE_AUSPOST) then
119 begin
120 // Format control code (FCC)
121 case Length(ASource) of
122 8 : fcc := '11';
123 16: begin
124 Result := is_sane(NEON, ASource);
125 fcc := '59';
126 end;
127 13: fcc := '59';
128 23: begin
129 Result := is_sane(NEON, ASource);
130 fcc := '62';
131 end;
132 18: fcc := '62';
133 else
134 ASymbol^.SetErrorText('Auspost input is wrong length');
135 Result := ERROR_TOO_LONG;
136 exit;
137 end;
138 if (Result = ERROR_INVALID_DATA) then
139 begin
140 ASymbol^.SetErrorText('Invalid characters in data');
141 exit;
142 end;
143 end
144 else
145 begin
146 if (Length(ASource) > 8) then
147 begin
148 ASymbol^.SetErrorText('Auspost input is too long');
149 Result := ERROR_TOO_LONG;
150 exit;
151 end;
152 case ASymbol^.symbology of
153 BARCODE_AUSREPLY:
154 fcc := '45';
155 BARCODE_AUSROUTE:
156 fcc := '87';
157 BARCODE_AUSREDIRECT:
158 fcc := '92';
159 end;
160
161 //Add leading zeros as required
162 localstr := StringOfChar('0', 8 - Length(ASource)) + localstr;
163 end;
164
165 Result := is_sane(GDSET, localstr);
166 if (Result = ERROR_INVALID_DATA) then
167 begin
168 ASymbol^.SetErrorText('Invalid characters in data');
169 exit;
170 end;
171
172 // Verifiy that the first 8 characters are numbers
173 dpid := copy(localstr, 1, 8);
174 Result := is_sane(NEON, dpid);
175 if (Result = ERROR_INVALID_DATA) then
176 begin
177 ASymbol^.SetErrorText('Invalid characters in DPID');
178 exit;
179 end;
180
181 // START character
182 data_pattern := '13';
183
184 // Encode the FCC
185 for i := 1 to 2 do
186 lookup(NEON, AusNTable, fcc[i], data_pattern);
187
188 // Delivery Point Identifier (DPID)
189 for i := 1 to 8 do
190 lookup(NEON, AusNTable, dpid[i], data_pattern);
191
192 // Customer Information
193 len := Length(localstr);
194 if (len > 8) then
195 begin
196 if (len = 13) or (len = 18) then
197 begin
198 for i := 9 to len do
199 lookup(GDSET, AusCTable, localstr[i], data_pattern);
200 end
201 else if (len = 16) or (len = 23) then
202 begin
203 for i := 9 to len do
204 lookup(NEON, AusNTable, localstr[i], data_pattern);
205 end;
206 end;
207
208 // Filler bar
209 len := Length(data_pattern);
210 if (len = 22) or (len = 37) or (len = 52) then
211 data_pattern := data_pattern + '3';
212
213 // Reed Solomon error correction
214 rs_error_correction(data_pattern);
215
216 // STOP character
217 data_pattern := data_pattern + '13';
218
219 // Turn the symbol into a bar pattern ready for plotting
220 writer := 0;
221 len := Length(data_pattern);
222 for i := 1 to len do
223 begin
224 if ((data_pattern[i] = '1') or (data_pattern[i] = '0')) then
225 set_module(ASymbol, 0, writer);
226 set_module(ASymbol, 1, writer);
227 if ((data_pattern[i] = '2') or (data_pattern[i] = '0')) then
228 set_module(ASymbol, 2, writer);
229 Inc(writer, 2);
230 end;
231
232 // Store parameters in Zint symbol
233 ASymbol^.rows := 3;
234 ASymbol^.row_height[0] := 3;
235 ASymbol^.row_height[1] := 2;
236 ASymbol^.row_height[2] := 3;
237 ASymbol^.width := writer - 1;
238 ASymbol^.SetText(localstr);
239end;
240
241end.
242
Note: See TracBrowser for help on using the repository browser.