source: trunk/Packages/lazbarcodes/src/lbc_code128.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: 29.1 KB
Line 
1{ lbc_code128.pas - Handles Code_128, ean_128, ean_14, nve_18
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
9unit lbc_code128;
10
11{$IFDEF FPC}
12{$mode objfpc}{$H+}
13{$ENDIF}
14
15interface
16
17uses
18 Types,
19 zint;
20
21function code_128(ASymbol: PointerTo_zint_symbol; ASource: PByte; ALength: Integer): Integer;
22function ean_128(ASymbol: PointerTo_zint_symbol; ASource: PByte; ALength: Integer): Integer;
23function nve_18(ASymbol: PointerTo_zint_symbol; ASource: PByte; ALength: Integer): Integer;
24function ean_14(Asymbol: PointerTo_zint_symbol; ASource: PByte; ALength: Integer): Integer;
25
26implementation
27
28uses
29 SysUtils, lbc_common, lbc_gs1, lbc_helper;
30
31const
32 {%H-}DPDSET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*';
33
34type
35 TGlobalList = array[0..1] of array[0..169] of Integer;
36
37const
38 {Code 128 tables checked against ISO/IEC 15417:2007 }
39
40 // Code 128 character encodation - Table 1
41 C128Table : array[0..106] of String = (
42 '212222', '222122', '222221', '121223', '121322',
43 '131222', '122213', '122312', '132212', '221213',
44 '221312', '231212', '112232', '122132', '122231',
45 '113222', '123122', '123221', '223211', '221132',
46 '221231', '213212', '223112', '312131', '311222',
47 '321122', '321221', '312212', '322112', '322211',
48 '212123', '212321', '232121', '111323', '131123',
49 '131321', '112313', '132113', '132311', '211313',
50 '231113', '231311', '112133', '112331', '132131',
51 '113123', '113321', '133121', '313121', '211331',
52 '231131', '213113', '213311', '213131', '311123',
53 '311321', '331121', '312113', '312311', '332111',
54 '314111', '221411', '431111', '111224', '111422',
55 '121124', '121421', '141122', '141221', '112214',
56 '112412', '122114', '122411', '142112', '142211',
57 '241211', '221114', '413111', '241112', '134111',
58 '111242', '121142', '121241', '114212', '124112',
59 '124211', '411212', '421112', '421211', '212141',
60 '214121', '412121', '111143', '111341', '131141',
61 '114113', '114311', '411113', '411311', '113141',
62 '114131', '311141', '411131', '211412', '211214',
63 '211232', '2331112'
64 );
65
66 {%H-}_TRUE = 1;
67 _FALSE = 0;
68 SHIFTA = 90;
69 LATCHA = 91;
70 SHIFTB = 92;
71 LATCHB = 93;
72 {%H-}SHIFTC = 94;
73 LATCHC = 95;
74 AORB = 96;
75 ABORC = 97;
76 {%H-}CANDB = 98;
77 {%H-}CANDBB = 99;
78
79
80function parunmodd(llyth: Byte): Integer;
81var
82 modd: Integer;
83begin
84 modd := SHIFTB;
85
86 if (llyth <= 31) then
87 modd := SHIFTA
88 else if ((llyth >= 48) and (llyth <= 57)) then
89 modd := ABORC
90 else if (llyth <= 95) then
91 modd := AORB
92 else if (llyth <= 127) then
93 modd := SHIFTB
94 else if (llyth <= 159) then
95 modd := SHIFTA
96 else if (llyth <= 223) then
97 modd := AORB;
98
99 Result := modd;
100end;
101
102function parunmodd(llyth: Char): Integer;
103begin
104 Result := parunmodd(Ord(llyth));
105end;
106
107
108{ Bring together same type blocks }
109procedure grwp(var indexlist: Integer; var list: TGlobalList);
110var
111 i, j: Integer;
112begin
113 if (indexlist <= 1) then
114 exit;
115
116 // Because i is modified inside the loop, we have to use "while"
117 i := 1;
118 while i < indexlist do
119 begin
120 if (list[1, i - 1] = list[1, i]) then
121 begin
122 { bring together }
123 list[0, i - 1] := list[0, i - 1] + list[0, i];
124
125 { decrease the list }
126 for j := i + 1 to indexlist - 1 do
127 begin
128 list[0, j - 1] := list[0, j];
129 list[1, j - 1] := list[1, j];
130 end;
131 dec(indexlist);
132 dec(i);
133 end;
134 inc(i);
135 end;
136end;
137
138 { Implements rules from ISO 15417 Annex E }
139procedure dxsmooth(var indexlist: Integer; var list: TGlobalList);
140var
141 i, current, _length, last, next: Integer;
142begin
143 for i := 0 to indexlist- 1 do
144 begin
145 current := list[1, i];
146 _length := list[0, i];
147
148 if (i <> 0) then
149 last := list[1, i - 1]
150 else
151 last := _FALSE;
152
153 if (i <> indexlist - 1) then
154 next := list[1, i + 1]
155 else
156 next := _FALSE;
157
158 if(i = 0) then
159 begin { first block }
160 if ((indexlist = 1) and (_length = 2) and (current = ABORC)) then
161 { Rule 1a }
162 list[1, i] := LATCHC;
163
164 if (current = ABORC) then
165 begin
166 if (_length >= 4) then
167 { Rule 1b }
168 list[1, i] := LATCHC
169 else
170 begin
171 list[1, i] := AORB;
172 current := AORB;
173 end;
174 end;
175
176 if (current = SHIFTA) then
177 { Rule 1c }
178 list[1, i] := LATCHA;
179
180 if (current = AORB) and (next = SHIFTA) then
181 begin
182 { Rule 1c }
183 list[1, i] := LATCHA;
184 current := LATCHA;
185 end;
186
187 if (current = AORB) then
188 { Rule 1d }
189 list[1, i] := LATCHB;
190 end
191 else
192 begin
193 if (current = ABORC) and (_length >= 4) then
194 begin
195 { Rule 3 }
196 list[1, i] := LATCHC;
197 current := LATCHC;
198 end;
199 if (current = ABORC) then
200 begin
201 list[1, i] := AORB;
202 current := AORB;
203 end;
204 if (current = AORB) and (last = LATCHA) then
205 begin
206 list[1, i] := LATCHA;
207 current := LATCHA;
208 end;
209 if (current = AORB) and (last = LATCHB) then
210 begin
211 list[1, i] := LATCHB;
212 current := LATCHB;
213 end;
214 if (current = AORB) and (next = SHIFTA) then
215 begin
216 list[1, i] := LATCHA;
217 current := LATCHA;
218 end;
219 if (current = AORB) and (next = SHIFTB) then
220 begin
221 list[1, i] := LATCHB;
222 current := LATCHB;
223 end;
224 if (current = AORB) then
225 begin
226 list[1, i] := LATCHB;
227 current := LATCHB;
228 end;
229 if (current = SHIFTA) and (_length > 1) then
230 begin
231 { Rule 4 }
232 list[1, i] := LATCHA;
233 current := LATCHA;
234 end;
235 if (current = SHIFTB) and (_length > 1) then
236 begin
237 { Rule 5 }
238 list[1, i] := LATCHB;
239 current := LATCHB;
240 end;
241 if (current = SHIFTA) and (last = LATCHA) then
242 begin
243 list[1, i] := LATCHA;
244 current := LATCHA;
245 end;
246 if (current = SHIFTB) and (last = LATCHB) then
247 begin
248 list[1, i] := LATCHB;
249 current := LATCHB;
250 end;
251 if (current = SHIFTA) and (last = LATCHC) then
252 begin
253 list[1, i] := LATCHA;
254 current := LATCHA;
255 end;
256 if (current = SHIFTB) and (last = LATCHC) then
257 begin
258 list[1, i] := LATCHB; //current := LATCHB;
259 end;
260 end; { Rule 2 is implimented elsewhere, Rule 6 is implied }
261 end;
262 grwp(indexlist, list);
263end;
264
265 { Translate Code 128 Set A characters into barcodes.
266 This set handles all control characters NULL to US. }
267procedure c128_set_a(source: Byte; var dest: String;
268 var values: TIntegerDynArray; var bar_chars: Integer);
269begin
270 { limit the range to 0-127 }
271 source := source and 127;
272
273 if (source < 32) then
274 source := source + 64
275 else
276 source := source - 32;
277
278 dest := dest + C128Table[source];
279 values[bar_chars] := source;
280 Inc(bar_chars);
281end;
282
283 { Translate Code 128 Set B characters into barcodes.
284 This set handles all characters which are not part of long numbers and not
285 control characters. }
286procedure c128_set_b(source: Byte; var dest: String;
287 var values: TIntegerDynArray; var bar_chars: Integer);
288begin
289 { limit the range to 0-127 }
290 source := source and 127;
291 source := source - 32;
292
293 dest := dest + C128Table[source];
294 values[bar_chars] := source;
295 Inc(bar_chars);
296end;
297
298 { Translate Code 128 Set C characters into barcodes.
299 This set handles numbers in a compressed form. }
300procedure c128_set_c(source_a: Byte; source_b: Byte; var dest: String;
301 var values: TIntegerDynArray; var bar_chars: Integer);
302var
303 weight: Integer;
304 begin
305 weight := (10 * StrToInt(Chr(source_a))) + StrToInt(Chr(source_b));
306 dest := dest + C128Table[weight];
307 values[bar_chars] := weight;
308 Inc(bar_chars);
309end;
310
311{ Handles Code 128 and NVE-18. }
312function code_128(ASymbol: PointerTo_zint_symbol; ASource: PByte;
313 ALength: Integer): Integer;
314var
315 i, j, k, bar_characters, read, total_sum: Integer;
316 values: TIntegerDynArray = nil;
317 error_number, indexchaine, indexlist, sourcelen, f_state: Integer;
318 _set: TCharDynArray = nil;
319 fset: TCharDynArray = nil;
320 last_set, current_set: Char;
321 mode: Integer;
322 glyph_count: Single;
323 dest: String;
324 list: TGlobalList;
325 P: PByte;
326begin
327 list := Default(TGlobalList);
328
329 SetLength(_set, 170);
330 FillChar(_set[0], Length(_set), ord(' '));
331
332 SetLength(fset, 170);
333 FillChar(fset[0], Length(fset), ord(' '));
334
335 SetLength(values, 170);
336
337 current_set := ' ';
338 error_number := 0;
339
340 sourcelen := ALength;
341
342 bar_characters := 0;
343 f_state := 0;
344
345 if (sourcelen > 160) then
346 begin
347 { This only blocks ridiculously long input - the actual length of the
348 resulting barcode depends on the type of data, so this is trapped later }
349 ASymbol^.SetErrorText('Input too long (max 80 characters)');
350 Result := ERROR_TOO_LONG;
351 exit;
352 end;
353
354 { Detect extended ASCII characters }
355 P := ASource;
356 for i := 0 to sourcelen - 1 do
357 begin
358 if (P^ >= 128) then
359 fset[i] := 'f';
360 inc(P);
361 end;
362 fset[sourcelen] := #0;
363
364 { Decide when to latch to extended mode - Annex E note 3 }
365 j := 0;
366 for i := 0 to sourcelen - 1 do
367 begin
368 if (fset[i] = 'f') then
369 inc(j)
370 else
371 j := 0;
372
373 if (j >= 5) then
374 begin
375 for k := i downto (i - 4) do
376 fset[k] := 'F';
377 end;
378
379 if ((j >= 3) and (i = sourcelen - 1)) then
380 begin
381 for k := i downto i - 2 do
382 fset[k] := 'F';
383 end;
384 end;
385
386 { Decide if it is worth reverting to 646 encodation for a few
387 characters as described in 4.3.4.2 (d) }
388 for i := 1 to sourcelen - 1 do
389 begin
390 if ((fset[i - 1] = 'F') and (fset[i] = ' ')) then
391 begin
392 { Detected a change from 8859-1 to 646 - count how long for }
393 j := 0;
394 while (fset[i + j] = ' ') and (i + j < sourcelen) do
395 Inc(j);
396
397 if (j < 5) or ((j < 3) and (i + j = sourcelen - 1)) then
398 begin
399 { Uses the same figures recommended by Annex E note 3 }
400 { Change to shifting back rather than latching back }
401 for k := 0 to j - 1 do
402 fset[i + k] := 'n';
403 end;
404 end;
405 end;
406
407 { Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E }
408 indexlist := 0;
409 indexchaine := 0;
410
411 mode := parunmodd(ASource[indexchaine]);
412 if ((ASymbol^.symbology = BARCODE_CODE128B) and (mode = ABORC)) then
413 mode := AORB;
414
415 FillChar(list[0], 170, 0);
416
417 repeat
418 list[1, indexlist] := mode;
419 while ((list[1, indexlist] = mode) and (indexchaine < sourcelen)) do
420 begin
421 Inc(list[0, indexlist]);
422 Inc(indexchaine);
423 mode := parunmodd(ASource[indexchaine]);
424 if ((ASymbol^.symbology = BARCODE_CODE128B) and (mode = ABORC)) then
425 mode := AORB;
426 end;
427 Inc(indexlist);
428 until not (indexchaine < sourcelen);
429
430 dxsmooth(indexlist, list);
431
432 { Resolve odd length LATCHC blocks }
433 if ((list[1, 0] = LATCHC) and ((list[0, 0] and 1) <> 0)) then
434 begin
435 { Rule 2 }
436 Inc(list[0, 1]);
437 Dec(list[0, 0]);
438 if (indexlist = 1) then
439 begin
440 list[0, 1] := 1;
441 list[1, 1] := LATCHB;
442 indexlist := 2;
443 end;
444 end;
445 if (indexlist > 1) then
446 begin
447 for i := 1 to indexlist - 1 do
448 begin
449 if ((list[1, i] = LATCHC) and ((list[0, i] and 1) <> 0)) then
450 begin
451 { Rule 3b }
452 Inc(list[0, i - 1]);
453 Dec(list[0, i]);
454 end;
455 end;
456 end;
457
458 { Put set data into set[] }
459
460 read := 0;
461 for i := 0 to indexlist - 1 do
462 begin
463 for j := 0 to list[0, i] - 1 do
464 begin
465 case(list[1, i]) of
466 SHIFTA: _set[read] := 'a';
467 LATCHA: _set[read] := 'A';
468 SHIFTB: _set[read] := 'b';
469 LATCHB: _set[read] := 'B';
470 LATCHC: _set[read] := 'C';
471 end;
472 Inc(read);
473 end;
474 end;
475
476 { Adjust for strings which start with shift characters - make them latch instead }
477 i := 0;
478 while _set[i] = 'a' do
479 begin
480 _set[i] := 'A';
481 Inc(i);
482 end;
483
484 i := 0;
485 while _set[i] = 'b' do
486 begin
487 _set[i] := 'B';
488 Inc(i);
489 end;
490
491 { Now we can calculate how long the barcode is going to be - and stop it from
492 being too long }
493 last_set := ' ';
494 glyph_count := 0.0;
495 for i := 0 to sourcelen - 1 do
496 begin
497 if ((_set[i] = 'a') or (_set[i] = 'b')) then
498 glyph_count := glyph_count + 1.0;
499
500 if ((fset[i] = 'f') or (fset[i] = 'n')) then
501 glyph_count := glyph_count + 1.0;
502
503 if (((_set[i] = 'A') or (_set[i] = 'B')) or (_set[i] = 'C')) then
504 begin
505 if (_set[i] <> last_set) then
506 begin
507 last_set := _set[i];
508 glyph_count := glyph_count + 1.0;
509 end;
510 end;
511 if (i = 0) then
512 begin
513 if (fset[i] = 'F') then
514 glyph_count := glyph_count + 2.0;
515 end
516 else
517 begin
518 if ((fset[i] = 'F') and (fset[i - 1] <> 'F')) then
519 glyph_count := glyph_count + 2.0;
520
521 if ((fset[i] <> 'F') and (fset[i - 1] = 'F')) then
522 glyph_count := glyph_count + 2.0;
523 end;
524
525 if(_set[i] = 'C') then
526 glyph_count := glyph_count + 0.5
527 else
528 glyph_count := glyph_count + 1.0;
529 end;
530
531 if (glyph_count > 80.0) then
532 begin
533 ASymbol^.SetErrorText('Input too long (max 80 characters)');
534 Result := ERROR_TOO_LONG;
535 exit;
536 end;
537
538 { So now we know what start character to use - we can get on with it! }
539 dest := '';
540 if (ASymbol^.output_options and READER_INIT) <> 0 then
541 begin
542 { Reader Initialisation mode }
543 case _set[0] of
544 'A': { Start A }
545 begin
546 dest := dest + C128Table[103];
547 values[0] := 103;
548 current_set := 'A';
549 dest := dest + C128Table[96]; { FNC3 }
550 values[1] := 96;
551 Inc(bar_characters);
552 end;
553 'B': { Start B }
554 begin
555 dest := dest + C128Table[104];
556 values[0] := 104;
557 current_set := 'B';
558 dest := dest + C128Table[96]; { FNC3 }
559 values[1] := 96;
560 Inc(bar_characters);
561 end;
562 'C': { Start C }
563 begin
564 dest := dest + C128Table[104]; { Start B }
565 values[0] := 105;
566 dest := dest + C128Table[96]; { FNC3 }
567 values[1] := 96;
568 dest := dest + C128Table[99]; { Code C }
569 values[2] := 99;
570 Inc(bar_characters, 2);
571 current_set := 'C';
572 end;
573 end;
574 end
575 else
576 begin
577 { Normal mode }
578 case _set[0] of
579 'A': { Start A }
580 begin
581 dest := dest + C128Table[103];
582 values[0] := 103;
583 current_set := 'A';
584 end;
585 'B': { Start B }
586 begin
587 dest := dest + C128Table[104];
588 values[0] := 104;
589 current_set := 'B';
590 end;
591 'C': { Start C }
592 begin
593 dest := dest + C128Table[105];
594 values[0] := 105;
595 current_set := 'C';
596 end;
597 end;
598 end;
599 Inc(bar_characters);
600 //last_set := _set[0];
601
602 if(fset[0] = 'F') then
603 begin
604 case current_set of
605 'A':
606 begin
607 dest := dest + C128Table[101];
608 dest := dest + C128Table[101];
609 values[bar_characters] := 101;
610 values[bar_characters + 1] := 101;
611 end;
612 'B':
613 begin
614 dest := dest + C128Table[100];
615 dest := dest + C128Table[100];
616 values[bar_characters] := 100;
617 values[bar_characters + 1] := 100;
618 end;
619 end;
620 Inc(bar_characters, 2);
621 f_state := 1;
622 end;
623
624 { Encode the data }
625 read := 0;
626 repeat
627 if ((read <> 0) and (_set[read] <> current_set)) then
628 begin { Latch different code set }
629 case _set[read] of
630 'A':
631 begin
632 dest := dest + C128Table[101];
633 values[bar_characters] := 101;
634 Inc(bar_characters);
635 current_set := 'A';
636 end;
637 'B':
638 begin
639 dest := dest + C128Table[100];
640 values[bar_characters] := 100;
641 Inc(bar_characters);
642 current_set := 'B';
643 end;
644 'C':
645 begin
646 dest := dest + C128Table[99];
647 values[bar_characters] := 99;
648 Inc(bar_characters);
649 current_set := 'C';
650 end;
651 end;
652 end;
653
654 if (read <> 0) then
655 begin
656 if ((fset[read] = 'F') and (f_state = 0)) then
657 begin
658 { Latch beginning of extended mode }
659 case current_set of
660 'A':
661 begin
662 dest := dest + C128Table[101];
663 dest := dest + C128Table[101];
664 values[bar_characters] := 101;
665 values[bar_characters + 1] := 101;
666 end;
667 'B':
668 begin
669 dest := dest + C128Table[100];
670 dest := dest + C128Table[100];
671 values[bar_characters] := 100;
672 values[bar_characters + 1] := 100;
673 end;
674 end;
675 Inc(bar_characters, 2);
676 f_state := 1;
677 end;
678 if ((fset[read] = ' ') and (f_state = 1)) then
679 begin
680 { Latch end of extended mode }
681 case current_set of
682 'A':
683 begin
684 dest := dest + C128Table[101];
685 dest := dest + C128Table[101];
686 values[bar_characters] := 101;
687 values[bar_characters + 1] := 101;
688 end;
689 'B':
690 begin
691 dest := dest + C128Table[100];
692 dest := dest + C128Table[100];
693 values[bar_characters] := 100;
694 values[bar_characters + 1] := 100;
695 end;
696 end;
697 Inc(bar_characters, 2);
698 f_state := 0;
699 end;
700 end;
701
702 if ((fset[read] = 'f') or (fset[read] = 'n')) then
703 begin
704 { Shift to or from extended mode }
705 case current_set of
706 'A':
707 begin
708 dest := dest + C128Table[101]; { FNC 4 }
709 values[bar_characters] := 101;
710 end;
711 'B':
712 begin
713 dest := dest + C128Table[100]; { FNC 4 }
714 values[bar_characters] := 100;
715 end;
716 end;
717 Inc(bar_characters);
718 end;
719
720 if ((_set[read] = 'a') or (_set[read] = 'b')) then
721 begin
722 { Insert shift character }
723 dest := dest + C128Table[98];
724 values[bar_characters] := 98;
725 Inc(bar_characters);
726 end;
727
728 case _set[read] of
729 { Encode data characters }
730 'a', 'A':
731 begin
732 c128_set_a(ASource[read], dest, values, bar_characters);
733 Inc(read);
734 end;
735 'b', 'B':
736 begin
737 c128_set_b(ASource[read], dest, values, bar_characters);
738 Inc(read);
739 end;
740 'C':
741 begin
742 c128_set_c(ASource[read], ASource[read + 1], dest, values, bar_characters);
743 Inc(read, 2);
744 end;
745 end;
746 until not (read < sourcelen);
747
748 { check digit calculation }
749 total_sum := 0;
750
751 for i := 0 to bar_characters - 1 do
752 begin
753 if (i > 0) then
754 values[i] := values[i] * i;
755 Inc(total_sum, values[i]);
756 end;
757 dest := dest + C128Table[total_sum mod 103];
758
759 // STOP character
760 dest := dest + C128Table[106];
761 expand(ASymbol, dest);
762
763 ASymbol^.SetText(PChar(ASource));
764
765 result := error_number;
766end;
767
768{ Handle EAN-128 (Now known as GS1-128) }
769function ean_128(ASymbol: PointerTo_zint_symbol; ASource: PByte;
770 ALength: Integer): Integer;
771var
772 values: TIntegerDynArray = nil;
773 bar_characters, read, total_sum: Integer;
774 error_number, indexchaine, indexliste: Integer;
775 _set: TCharDynArray = nil;
776 mode: Integer;
777 last_set: Char;
778 glyph_count: Single;
779 dest: String;
780 separator_row, linkage_flag, c_count: Integer;
781 reduced: TCharDynArray = nil;
782 i, j: Integer;
783 list: TGlobalList;
784 P: PByte;
785begin
786 list := Default(TGlobalList);
787
788 SetLength(values, 170);
789 SetLength(_set, 170);
790 SetLength(reduced, ALength + 1);
791 error_number := 0;
792 linkage_flag := 0;
793 bar_characters := 0;
794 separator_row := 0;
795
796 FillChar(_set[0], Length(_set), ord(' '));
797
798 if (ALength > 160) then
799 begin
800 { This only blocks ridiculously long input - the actual Length(source) of the
801 resulting barcode depends on the type of data, so this is trapped later }
802 ASymbol^.SetErrorText('Input too long (max 160 characters)');
803 Result := ERROR_TOO_LONG;
804 exit;
805 end;
806
807 P := ASource;
808 for i := 0 to ALength - 1 do
809 begin
810 if (P^ = 0) then
811 begin
812 { Null characters not allowed! }
813 ASymbol^.SetErrorText('NULL character in input data');
814 Result := ERROR_INVALID_DATA;
815 exit;
816 end;
817 inc(P);
818 end;
819
820 { If part of a composite symbol make room for the separator pattern }
821 if (ASymbol^.symbology = BARCODE_EAN128_CC) then
822 begin
823 separator_row := ASymbol^.rows;
824 ASymbol^.row_height[ASymbol^.rows] := 1;
825 inc(ASymbol^.rows);
826 end;
827
828 if(ASymbol^.input_mode <> GS1_MODE) then
829 begin
830 { GS1 data has not been checked yet }
831 error_number := gs1_verify(ASymbol, ASource, ALength, reduced);
832 if (error_number <> 0) then begin
833 Result := error_number;
834 exit;
835 end;
836 end;
837
838 { Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E }
839 indexliste := 0;
840 indexchaine := 0;
841
842 mode := parunmodd(Ord(reduced[indexchaine]));
843 if (reduced[indexchaine] = '[') then
844 mode := ABORC;
845
846 FillChar(list[0], Length(list[0]), 0);
847
848 repeat
849 list[1, indexliste] := mode;
850 while ((list[1, indexliste] = mode) and (indexchaine < strlen(reduced))) do
851 begin
852 inc(list[0, indexliste]);
853 Inc(indexchaine);
854 mode := parunmodd(reduced[indexchaine]);
855 if (reduced[indexchaine] = '[') then mode := ABORC;
856 end;
857 inc(indexliste);
858 until not (indexchaine < strlen(reduced));
859
860 dxsmooth(indexliste, list);
861
862 { Put set data into _set[] }
863 read := 0;
864 for i := 0 to indexliste - 1 do
865 begin
866 for j := 0 to list[0][i] - 1 do
867 begin
868 case list[1, i] of
869 SHIFTA: _set[read] := 'a';
870 LATCHA: _set[read] := 'A';
871 SHIFTB: _set[read] := 'b';
872 LATCHB: _set[read] := 'B';
873 LATCHC: _set[read] := 'C';
874 end;
875 Inc(read);
876 end;
877 end;
878
879 { Watch out for odd-Length(source) Mode C blocks }
880 c_count := 0;
881 for i := 0 to read - 1 do
882 begin
883 if (_set[i] = 'C') then
884 begin
885 if (reduced[i] = '[') then
886 begin
887 if (c_count and 1) <> 0 then
888 begin
889 if ((i - c_count) <> 0) then
890 _set[i - c_count] := 'B'
891 else
892 _set[i - 1] := 'B';
893 end;
894 c_count := 0;
895 end
896 else
897 Inc(c_count);
898 end
899 else
900 begin
901 if (c_count and 1) <> 0 then
902 begin
903 if ((i - c_count) <> 0) then
904 _set[i - c_count] := 'B'
905 else
906 _set[i - 1] := 'B';
907 end;
908 c_count := 0;
909 end;
910 end;
911
912 if (c_count and 1) <> 0 then
913 begin
914 if (read - c_count <> 0) then
915 _set[read - c_count] := 'B'
916 else
917 _set[read - 1] := 'B';
918 end;
919
920 for i := 1 to read - 2 do
921 begin
922 if ((_set[i] = 'C') and ((_set[i - 1] = 'B') and (_set[i + 1] = 'B'))) then
923 _set[i] := 'B';
924 end;
925
926 { Now we can calculate how long the barcode is going to be - and stop it from
927 being too long }
928 last_set := ' ';
929 glyph_count := 0.0;
930 for i := 0 to strlen(reduced) - 1 do
931 begin
932 if ((_set[i] = 'a') or (_set[i] = 'b')) then
933 glyph_count := glyph_count + 1.0;
934
935 if (((_set[i] = 'A') or (_set[i] = 'B')) or (_set[i] = 'C')) then
936 begin
937 if (_set[i] <> last_set) then
938 begin
939 last_set := _set[i];
940 glyph_count := glyph_count + 1.0;
941 end;
942 end;
943
944 if ((_set[i] = 'C') and (reduced[i] <> '[')) then
945 glyph_count := glyph_count + 0.5
946 else
947 glyph_count := glyph_count + 1.0;
948 end;
949
950 if(glyph_count > 80.0) then
951 begin
952 ASymbol^.SetErrorText('Input too long (max 80 characters)');
953 result := ERROR_TOO_LONG;
954 exit;
955 end;
956
957 { So now we know what start character to use - we can get on with it! }
958 dest := '';
959 case _set[1] of
960 'A': { Start A }
961 begin
962 dest := dest + C128Table[103];
963 values[0] := 103;
964 end;
965 'B': { Start B }
966 begin
967 dest := dest + C128Table[104];
968 values[0] := 104;
969 end;
970 'C': { Start C }
971 begin
972 dest := dest + C128Table[105];
973 values[0] := 105;
974 end;
975 end;
976 Inc(bar_characters);
977
978 dest := dest + C128Table[102];
979 values[1] := 102;
980 Inc(bar_characters);
981
982 { Encode the data }
983 read := 0;
984 repeat
985 if ((read <> 0) and (_set[read] <> _set[read - 1])) then
986 begin { Latch different code set }
987 case (_set[read]) of
988 'A':
989 begin
990 dest := dest + C128Table[101];
991 values[bar_characters] := 101;
992 inc(bar_characters);
993 end;
994
995 'B':
996 begin
997 dest := dest + C128Table[100];
998 values[bar_characters] := 100;
999 inc(bar_characters);
1000 end;
1001 'C':
1002 begin
1003 dest := dest + C128Table[99];
1004 values[bar_characters] := 99;
1005 Inc(bar_characters);
1006 end
1007 end;
1008 end;
1009
1010 if (_set[read] = 'a') or (_set[read] = 'b') then
1011 begin
1012 { Insert shift character }
1013 dest := dest + C128Table[98];
1014 values[bar_characters] := 98;
1015 Inc(bar_characters);
1016 end;
1017
1018 if (reduced[read] <> '[') then
1019 begin
1020 { Encode data characters }
1021 case _set[read] of
1022 'A', 'a':
1023 begin
1024 c128_set_a(Ord(reduced[read]), dest, values, bar_characters);
1025 Inc(read);
1026 end;
1027 'B', 'b':
1028 begin
1029 c128_set_b(Ord(reduced[read]), dest, values, bar_characters);
1030 Inc(read);
1031 end;
1032 'C':
1033 begin
1034 c128_set_c(Ord(reduced[read]), Ord(reduced[read + 1]), dest, values, bar_characters);
1035 Inc(read, 2);
1036 end;
1037 end;
1038 end
1039 else
1040 begin
1041 dest := dest + C128Table[102];
1042 values[bar_characters] := 102;
1043 Inc(bar_characters);
1044 Inc(read);
1045 end;
1046 until not (read < strlen(reduced));
1047
1048 { "...note that the linkage flag is an extra code set character between
1049 the last data character and the Symbol Check Character"
1050 (GS1 Specification) }
1051
1052 { Linkage flags in GS1-128 are determined by ISO/IEC 24723 section 7.4 }
1053
1054 case ASymbol^.option_1 of
1055 1, 2:
1056 begin // CC-A or CC-B 2D component
1057 case _set[strlen(reduced )- 1] of
1058 'A': linkage_flag := 100;
1059 'B': linkage_flag := 99;
1060 'C': linkage_flag := 101;
1061 end;
1062 end;
1063 3:
1064 begin // CC-C 2D component
1065 case _set[strlen(reduced) - 1] of
1066 'A': linkage_flag := 99;
1067 'B': linkage_flag := 101;
1068 'C': linkage_flag := 100;
1069 end;
1070 end;
1071 end;
1072
1073 if (linkage_flag <> 0) then
1074 begin
1075 dest := dest + C128Table[linkage_flag];
1076 values[bar_characters] := linkage_flag;
1077 Inc(bar_characters);
1078 end;
1079
1080 { check digit calculation }
1081 total_sum := 0;
1082 for i := 0 to bar_characters do
1083 begin
1084 if (i > 0) then
1085 values[i] := values[i] * i;
1086 inc(total_sum, values[i]);
1087 end;
1088 dest := dest + C128Table[total_sum mod 103];
1089 values[bar_characters] := total_sum mod 103;
1090 Inc(bar_characters);
1091
1092 // STOP character
1093 dest := dest + C128Table[106];
1094 values[bar_characters] := 106;
1095 Inc(bar_characters);
1096
1097 expand(ASymbol, dest);
1098
1099 { Add the separator pattern for composite symbols }
1100 if (ASymbol^.symbology = BARCODE_EAN128_CC) then
1101 begin
1102 for i := 0 to ASymbol^.width - 1 do
1103 begin
1104 if not module_is_set(ASymbol, separator_row + 1, i) then
1105 set_module(ASymbol, separator_row, i);
1106 end;
1107 end;
1108
1109 ASymbol^.text[0] := 0;
1110 P := ASource;
1111 for i := 0 to ALength - 1 do
1112 begin
1113 if ((P^ <> Ord('[')) and (P^ <> Ord(']'))) then
1114 ASymbol^.text[i] := P^;
1115
1116 if (P^ = Ord('[')) then
1117 ASymbol^.text[i] := Ord('(');
1118
1119 if (P^ = Ord(']')) then
1120 ASymbol^.text[i] := Ord(')');
1121
1122 inc(P);
1123 end;
1124
1125 Result := error_number;
1126end;
1127
1128{ Add check digit if encoding an NVE18 symbol }
1129function nve_18(ASymbol: PointerTo_zint_symbol; ASource: PByte;
1130 ALength: Integer): Integer;
1131var
1132 error_number, zeroes, nve_check, total_sum, sourcelen: Integer;
1133 ean128_equiv: TByteDynArray = nil;
1134 i: Integer;
1135begin
1136 SetLength(ean128_equiv, 25);
1137 FillChar(ean128_equiv[0], 25, 0);
1138
1139 sourcelen := ALength;
1140 if (sourcelen > 17) then
1141 begin
1142 ASymbol^.SetErrorText('Input too long (max 17 characters)');
1143 Result := ERROR_TOO_LONG;
1144 exit;
1145 end;
1146
1147 error_number := is_sane(NEON, ASource, ALength);
1148 if (error_number = ERROR_INVALID_DATA) then
1149 begin
1150 ASymbol^.SetErrorText('Invalid characters in data');
1151 Result := error_number;
1152 exit;
1153 end;
1154
1155 zeroes := 17 - sourcelen;
1156 ustrcpy(ean128_equiv, '[00]');
1157 FillChar(ean128_equiv[4], zeroes, Ord('0'));
1158 ean128_equiv[4 + zeroes] := 0;
1159 concat(PChar(@ean128_equiv[0]), PChar(ASource));
1160
1161 total_sum := 0;
1162 for i := sourcelen - 1 downto 0 do
1163 begin
1164 inc(total_sum, ctoi(Char(ASource[i])));
1165 if (((sourcelen - 1 - i) and 1) = 0) then
1166 Inc(total_sum, 2 * ctoi(Char(ASource[i])));
1167 end;
1168 nve_check := 10 - total_sum mod 10;
1169 if (nve_check = 10) then nve_check := 0;
1170 ean128_equiv[21] := Ord(itoc(nve_check));
1171 ean128_equiv[22] := 0;
1172
1173 error_number := ean_128(ASymbol, @ean128_equiv[0], ustrlen(ean128_equiv));
1174 result := error_number;
1175end;
1176
1177{ EAN-14 - A version of EAN-128 }
1178function ean_14(ASymbol: PointerTo_zint_symbol; ASource: PByte; ALength: Integer): Integer;
1179var
1180 i, sum, check_digit, zeros: Integer;
1181 ean128_equiv: String;
1182 b: byte;
1183begin
1184 if (ALength > 13) then
1185 begin
1186 ASymbol^.SetErrorText('Input wrong length (max 13 characters)');
1187 Result := ERROR_TOO_LONG;
1188 exit;
1189 end;
1190
1191 Result := is_sane(NEON, ASource, ALength);
1192 if (Result = ERROR_INVALID_DATA) then
1193 begin
1194 ASymbol^.SetErrorText('Invalid character in data');
1195 exit;
1196 end;
1197
1198 sum := 0;
1199 for i := ALength - 1 downto 0 do
1200 begin
1201 b := StrToInt(Char(ASource[i]));
1202 inc(sum, b);
1203 if not odd(ALength - 1 - i) then //(((ALength - 1 - i) and 1) = 0) then
1204 Inc(sum, 2 * b);
1205 end;
1206 check_digit := 10 - sum mod 10;
1207 if (check_digit = 10) then
1208 check_digit := 0;
1209
1210 zeros := 13 - ALength;
1211 ean128_equiv := '[01]' + StringOfChar('0', zeros) + PChar(ASource) + IntToStr(check_digit);
1212
1213 Result := ean_128(ASymbol, PByte(@ean128_equiv[1]), Length(ean128_equiv));
1214end;
1215
1216end.
1217
1218
Note: See TracBrowser for help on using the repository browser.