1 /*
2 * code128.c -- encoding for code128 (A, B, C)
3 *
4 * Copyright (c) 1999,2000 Alessandro Rubini (rubini@gnu.org)
5 * Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
6 * Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28
29 #include "barcode.h"
30
31 static char *codeset[] = {
32 "212222", "222122", "222221", "121223", "121322", /* 0 - 4 */
33 "131222", "122213", "122312", "132212", "221213",
34 "221312", "231212", "112232", "122132", "122231", /* 10 - 14 */
35 "113222", "123122", "123221", "223211", "221132",
36 "221231", "213212", "223112", "312131", "311222", /* 20 - 24 */
37 "321122", "321221", "312212", "322112", "322211",
38 "212123", "212321", "232121", "111323", "131123", /* 30 - 34 */
39 "131321", "112313", "132113", "132311", "211313",
40 "231113", "231311", "112133", "112331", "132131", /* 40 - 44 */
41 "113123", "113321", "133121", "313121", "211331",
42 "231131", "213113", "213311", "213131", "311123", /* 50 - 54 */
43 "311321", "331121", "312113", "312311", "332111",
44 "314111", "221411", "431111", "111224", "111422", /* 60 - 64 */
45 "121124", "121421", "141122", "141221", "112214",
46 "112412", "122114", "122411", "142112", "142211", /* 70 - 74 */
47 "241211", "221114", "413111", "241112", "134111",
48 "111242", "121142", "121241", "114212", "124112", /* 80 - 84 */
49 "124211", "411212", "421112", "421211", "212141",
50 "214121", "412121", "111143", "111341", "131141", /* 90 - 94 */
51 "114113", "114311", "411113", "411311", "113141",
52 "114131", "311141", "411131", "b1a4a2", "b1a2a4", /* 100 - 104 */
53 "b1a2c2", "b3c1a1b"
54 };
55
56 #define START_A 103
57 #define START_B 104
58 #define START_C 105
59 #define STOP 106
60 #define SHIFT 98 /* only A and B */
61 #define CODE_A 101 /* only B and C */
62 #define CODE_B 100 /* only A and C */
63 #define CODE_C 99 /* only A and B */
64 #define FUNC_1 102 /* all of them */
65 #define FUNC_2 97 /* only A and B */
66 #define FUNC_3 96 /* only A and B */
67 /* FUNC_4 is CODE_A when in A and CODE_B when in B */
68
69 #define SYMBOL_WID 11 /* all of them are 11-bar wide */
70
71 /*
72 * code 128-b includes all printable ascii chars
73 */
74
Barcode_128b_verify(unsigned char * text)75 int Barcode_128b_verify(unsigned char *text)
76 {
77 if (text[0] == '\0')
78 return -1;
79 while (*text && *text>=32 && !(*text&0x80))
80 text++;
81 if (*text)
82 return -1; /* a non-ascii char */
83 return 0; /* ok */
84 }
85
Barcode_128b_encode(struct Barcode_Item * bc)86 int Barcode_128b_encode(struct Barcode_Item *bc)
87 {
88 static char *text;
89 static char *partial; /* dynamic */
90 static char *textinfo; /* dynamic */
91 char *textptr;
92 int i, code, textpos, checksum = 0;
93
94 if (bc->partial)
95 free(bc->partial);
96 if (bc->textinfo)
97 free(bc->textinfo);
98 bc->partial = bc->textinfo = NULL; /* safe */
99
100 if (!bc->encoding)
101 bc->encoding = strdup("code 128-B");
102
103 text = bc->ascii;
104 if (!text) {
105 bc->error = EINVAL;
106 return -1;
107 }
108 /* the partial code is 6* (head + text + check + tail) + final + term. */
109 partial = malloc( (strlen(text) + 4) * 6 +2);
110 if (!partial) {
111 bc->error = errno;
112 return -1;
113 }
114
115 /* the text information is at most "nnn:fff:c " * strlen +term */
116 textinfo = malloc(10*strlen(text) + 2);
117 if (!textinfo) {
118 bc->error = errno;
119 free(partial);
120 return -1;
121 }
122
123 /* up to now, it was the same code as other encodings */
124
125 strcpy(partial, "0"); /* the first space */
126 strcat(partial, codeset[START_B]);
127 checksum += START_B; /* the start char is counted in the checksum */
128 textptr = textinfo;
129 textpos = SYMBOL_WID;
130
131 for (i=0; i<strlen(text); i++) {
132 if ( text[i] < 32 || (text[i] & 0x80)) {
133 bc->error = EINVAL; /* impossible if text is verified */
134 free(partial);
135 free(textinfo);
136 return -1;
137 }
138 code = text[i]-32;
139 strcat(partial, codeset[code]);
140 checksum += code * (i+1); /* first * 1 + second * 2 + third * 3... */
141 sprintf(textptr, "%i:12:%c ", textpos, text[i]);
142 textptr += strlen(textptr);
143 textpos += SYMBOL_WID; /* width of each code */
144 }
145 /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
146 checksum %= 103;
147 strcat(partial, codeset[checksum]);
148 /* and the end marker */
149 strcat(partial, codeset[STOP]);
150
151 bc->partial = partial;
152 bc->textinfo = textinfo;
153
154 return 0;
155 }
156
157 /*
158 * code 128-c is only digits, but two per symbol
159 */
160
Barcode_128c_verify(unsigned char * text)161 int Barcode_128c_verify(unsigned char *text)
162 {
163 if (text[0] == '\0')
164 return -1;
165 /* must be an even number of digits */
166 if (strlen(text)%2)
167 return -1;
168 /* and must be all digits */
169 for (; *text; text++)
170 if (!isdigit(*text))
171 return -1;
172 return 0;
173 }
174
Barcode_128c_encode(struct Barcode_Item * bc)175 int Barcode_128c_encode(struct Barcode_Item *bc)
176 {
177 static char *text;
178 static char *partial; /* dynamic */
179 static char *textinfo; /* dynamic */
180 char *textptr;
181 int i, code, textpos, checksum = 0;
182
183 if (bc->partial)
184 free(bc->partial);
185 if (bc->textinfo)
186 free(bc->textinfo);
187 bc->partial = bc->textinfo = NULL; /* safe */
188
189 if (!bc->encoding)
190 bc->encoding = strdup("code 128-C");
191
192 text = bc->ascii;
193 if (!text) {
194 bc->error = EINVAL;
195 return -1;
196 }
197 /* the partial code is 6* (head + text + check + tail) + final + term. */
198 partial = malloc( (strlen(text) + 3) * 6 +2);
199 if (!partial) {
200 bc->error = errno;
201 return -1;
202 }
203
204 /* the text information is at most "nnn.5:fff:c " * strlen +term */
205 textinfo = malloc(12*strlen(text) + 2);
206 if (!textinfo) {
207 bc->error = errno;
208 free(partial);
209 return -1;
210 }
211
212 strcpy(partial, "0"); /* the first space */
213 strcat(partial, codeset[START_C]);
214 checksum += START_C; /* the start char is counted in the checksum */
215 textptr = textinfo;
216 textpos = SYMBOL_WID;
217
218 for (i=0; text[i]; i+=2) {
219 if (!isdigit(text[i]) || !isdigit(text[i+1])) {
220 bc->error = EINVAL; /* impossible if text is verified */
221 free(partial);
222 free(textinfo);
223 return -1;
224 }
225 code = (text[i]-'0') * 10 + text[i+1]-'0';
226 strcat(partial, codeset[code]);
227 checksum += code * (i/2+1); /* first * 1 + second * 2 + third * 3... */
228
229 /* print as "%s", because we have ".5" positions */
230 sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos, text[i],
231 textpos + (double)SYMBOL_WID/2, text[i+1]);
232 textptr += strlen(textptr);
233 textpos += SYMBOL_WID; /* width of each code */
234 }
235 /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
236 checksum %= 103;
237 strcat(partial, codeset[checksum]);
238 /* and the end marker */
239 strcat(partial, codeset[STOP]);
240
241 bc->partial = partial;
242 bc->textinfo = textinfo;
243
244 return 0;
245 }
246
247 /*
248 * generic (full-featured) code128 implementation: it selects between
249 * A, B, C according to the data being encoded. F1, F2, F3, F4 are expressed
250 * using ascii chars 0xc1, 0xc2, 0xc3, 0xc4 (0301, 0302, 0303, 0304).
251 * Char '\0' is expressed by 0x80 (0200).
252 */
253
Barcode_128_verify(unsigned char * text)254 int Barcode_128_verify(unsigned char *text)
255 {
256 if (text[0] == '\0')
257 return -1;
258 while (*text && (*text<=0x80 || (*text >= 0xc1 && *text <= 0xc4)))
259 text++;
260 if (*text)
261 return -1; /* unencodable character */
262 return 0; /* ok */
263 }
264
265
266 /*
267 * These functions are extracted from Barcode_128_encode for clarity.
268 * It deals with choosing the symbols used to represent the text
269 * and returns a dynamic array of integers, terminated by -1.
270 *
271 * The algorithm used in choosing the codes comes from App 2 of
272 * "El Codigo Estandar EAN/UCC 128", courtesy of AECOC, Spain.
273 * Thanks to Dani Pardo for getting permission and giving me a copy
274 * of the document
275 */
276
277 #define NEED_CODE_A(c) ((c)<32 || (c)==0x80)
278 #define NEED_CODE_B(c) ((c)>=96 && (c)<128)
279
Barcode_a_or_b(unsigned char * text)280 static int Barcode_a_or_b(unsigned char *text)
281 {
282 for ( ; *text; text++) {
283 if (NEED_CODE_A(*text))
284 return 'A';
285 if (NEED_CODE_B(*text))
286 return 'B';
287 }
288 return 0; /* any */
289 }
290
291 /* code is either 'A' or 'B', and value must be valid */
Barcode_encode_as(int code,int value)292 static int Barcode_encode_as(int code, int value)
293 {
294
295 /* first check the special chars */
296 if (value == 0xC1) return FUNC_1;
297 if (value == 0xC2) return FUNC_2;
298 if (value == 0xC3) return FUNC_3;
299 if (value == 0xC4) { /* F4 */
300 if (code == 'A') return CODE_A;
301 return CODE_B;
302 }
303
304 /* then check ascii values */
305 if (value >= 0x20 && value <= 0x5F)
306 return value - 0x20; /* both codes */
307 if (value == 0x80) return 64; /* code A */
308 if (value < 0x20) return value+64; /* code A */
309 if (value >= 0x60) return value - 0x20; /* code B */
310 /* can't happen */
311 return -1;
312 }
313
Barcode_128_make_array(struct Barcode_Item * bc,int * lptr)314 static int *Barcode_128_make_array(struct Barcode_Item *bc, int *lptr)
315 {
316 int len, *codes;
317 unsigned char *s;
318 int i=0, j, code, checksum;
319
320 /* allocate twice the text length + 5, as this is the worst case */
321 len = 2 * strlen(bc->ascii) + 5;
322 codes = malloc(len * sizeof(int));
323 s = bc->ascii;
324
325 /* choose the starting code */
326 if (s[2]=='\0' && isdigit(s[0]) && isdigit(s[1])) {
327 code = 'C';
328 } else if (isdigit(s[0])&&isdigit(s[1]) && isdigit(s[2])&&isdigit(s[3])) {
329 code = 'C';
330 } else {
331 code = Barcode_a_or_b(s);
332 if (!code) code = 'B'; /* default */
333 }
334 codes[i++] = START_A + code - 'A';
335
336 for (s = bc->ascii; *s; /* increments are in the loop */) {
337 switch(code) {
338
339 case 'C':
340 if (s[0] == 0xC1) { /* F1 is valid */
341 codes[i++] = FUNC_1;
342 s++;
343 } else if (isdigit(s[0]) && isdigit(s[1])) {
344 /* encode two digits */
345 codes[i++] = (s[0]-'0') * 10 + s[1]-'0';
346 s += 2;
347 } else {
348 /* change code */
349 code = Barcode_a_or_b(s);
350 if (!code) code = 'B';
351 codes[i++] = (code == 'A') ? CODE_A : CODE_B;
352 }
353 break;
354
355 case 'B':
356 case 'A':
357 for (j=0; isdigit(s[j]); j++)
358 ;
359 if (j>=4) { /* if there are 4 or more digits, turn to C */
360 if (j&1) {
361 /* odd number: encode one first */
362 codes[i++] = *(s++) - ' ';
363 }
364 codes[i++] = CODE_C;
365 code = 'C';
366 } else if (code == 'A' && NEED_CODE_B(*s)) {
367 /* check whether we should use SHIFT or change code */
368 j = Barcode_a_or_b(s+1);
369 if (j == 'B') {
370 codes[i++] = CODE_B;
371 code = 'B';
372 } else {
373 codes[i++] = SHIFT;
374 codes[i++] = Barcode_encode_as('B', *s);
375 s++;
376 }
377 } else if (code == 'B' && NEED_CODE_A(*s)) {
378 /* check whether we should use SHIFT or change code */
379 j = Barcode_a_or_b(s+1);
380 if (j == 'A') {
381 codes[i++] = CODE_A;
382 code = 'A';
383 } else {
384 codes[i++] = SHIFT;
385 codes[i++] = Barcode_encode_as('A', *s);
386 s++;
387 }
388 } else {
389 codes[i++] = Barcode_encode_as(code, *s);
390 s++;
391 }
392 break;
393 }
394 }
395 /* add the checksum */
396 checksum = codes[0];
397 for (j=1; j<i; j++)
398 checksum += j * codes[j];
399 checksum %= 103;
400 codes[i++] = checksum;
401 codes[i++] = STOP;
402 if (i > len) {
403 fprintf(stderr, "impossible: length is > allocated len\n");
404 }
405 *lptr = i;
406 return codes;
407 }
408
409 /*
410 * Encoding is tricky, in that we cannot print the ascii
411 * representation in an easy way. Therefore, just skip non-printable
412 * chars and try to fit the rest somehow.
413 */
Barcode_128_encode(struct Barcode_Item * bc)414 int Barcode_128_encode(struct Barcode_Item *bc)
415 {
416 static char *text;
417 static char *partial; /* dynamic */
418 static char *textinfo; /* dynamic */
419 char *textptr;
420 int *codes; /* dynamic */
421 int i, c, len;
422 double textpos, size, step;
423
424 if (bc->partial)
425 free(bc->partial);
426 if (bc->textinfo)
427 free(bc->textinfo);
428 bc->partial = bc->textinfo = NULL; /* safe */
429
430 if (!bc->encoding)
431 bc->encoding = strdup("code 128");
432
433 text = bc->ascii;
434 if (!text) {
435 bc->error = EINVAL;
436 return -1;
437 }
438
439 codes = Barcode_128_make_array(bc, &len);
440 if (!codes) return -1;
441
442 /* the partial code is 6*codelen + ini + term (+margin) */
443 partial = malloc( 6 * len + 4);
444 if (!partial) {
445 bc->error = errno;
446 free(codes);
447 return -1;
448 }
449
450 /* the text information is at most "nnn.n:ff.f:c " * strlen +term */
451 textptr = textinfo = malloc(13*strlen(text) + 2);
452 if (!textinfo) {
453 bc->error = errno;
454 free(partial);
455 free(codes);
456 return -1;
457 }
458
459 /* up to now, it was almost the same code as other encodings */
460
461 strcpy(partial, "0"); /* the first space */
462 for (i=0; i<len; i++) /* the symbols */
463 strcat(partial, codeset[codes[i]]);
464
465 /* avoid bars that fall lower than other bars */
466 for (i=0; partial[i]; i++)
467 if (isalpha(partial[i]))
468 partial[i] += '1' - 'a';
469
470 /*
471 * the accompanying text: reserve a space for every char.
472 * F[1-4] are rendered as spaces (separators), other unprintable chars
473 * are rendered as underscoress (placeholders)
474 */
475
476 /*
477 * A size of 9 is good for code-C (used above), so 18 for each symbol,
478 * but we place an upper limit of 12 to avoid overlapping on the bars.
479 */
480 size = (int)(180.0 * (len-3) / strlen(text) + .5) / 10.0;
481 if (size > 12.0) size = 12.0;
482
483 /* align the text to the left, using its natural size */
484 step = (int)(10 * (size/18.0 * SYMBOL_WID) + .5) / 10.0;
485 textpos = SYMBOL_WID;
486
487 for (i=0; i<strlen(text); i++) {
488 c = text[i];
489 if (c < 32 || c == 0x80) c = '_'; /* not printable */
490 if (c > 0xc0) c = ' '; /* F code */
491 sprintf(textptr, "%g:%g:%c ", textpos, size, c);
492 textptr += strlen(textptr);
493 textpos += step;
494 }
495
496 bc->partial = partial;
497 bc->textinfo = textinfo;
498 free(codes);
499 return 0;
500 }
501
502 /*
503 * A raw 128 code is given as a sequence of space separated numbers
504 * from 0 to 105, starting from the start code to be (Leonid)
505 */
506
Barcode_128raw_verify(unsigned char * text)507 int Barcode_128raw_verify(unsigned char *text)
508 {
509 int n;
510 unsigned val;
511
512 if (!strlen(text))
513 return -1;
514 while (*text) {
515 if (sscanf(text, "%u%n", &val, &n) < 1)
516 return -1;
517 if (val > 105)
518 return -1;
519 text += n;
520 }
521 return 0;
522 }
523
Barcode_128raw_encode(struct Barcode_Item * bc)524 int Barcode_128raw_encode(struct Barcode_Item *bc)
525 {
526 static char *text;
527 static char *partial; /* dynamic */
528 static char *textinfo; /* dynamic */
529 char *textptr;
530 int i, n, count, code, textpos, checksum = 0;
531
532 if (bc->partial)
533 free(bc->partial);
534 if (bc->textinfo)
535 free(bc->textinfo);
536 bc->partial = bc->textinfo = NULL; /* safe */
537
538 if (!bc->encoding)
539 bc->encoding = strdup("128raw");
540
541 text = bc->ascii;
542 if (!text) {
543 bc->error = EINVAL;
544 return -1;
545 }
546 /*
547 * length of partial code is unknown in advance, but it is
548 * at most 6* (1+text/2 + check + tail) + final + terminator
549 */
550 partial = malloc( (3+ strlen(text)/2) * 6 + 2);
551 if (!partial) {
552 bc->error = errno;
553 return -1;
554 }
555
556 /* the text information is at most "nnn.5:fff:c " * 1+strlen/2 +term */
557 textinfo = malloc(12 * (1+strlen(text)/2) + 2);
558 if (!textinfo) {
559 bc->error = errno;
560 free(partial);
561 return -1;
562 }
563
564 strcpy(partial, "0"); /* the first space */
565 textptr = textinfo;
566 textpos = 0;
567
568 for (i=0, count = 0; i < strlen(text); count++) {
569 if (sscanf(text + i, "%u%n", &code, &n) < 1) {
570 bc->error = EINVAL; /* impossible if text is verified */
571 free(partial);
572 free(textinfo);
573 return -1;
574 }
575 strcat(partial, codeset[code]);
576
577 /*
578 * since the start code is part of the "raw" input, it is
579 * counted in the checksum by itself
580 */
581 if (!count) checksum += code; /* the start code */
582 else checksum += code * count; /* first * 1 + second * 2 ... */
583
584 /*
585 * print as "%s", because we have ".5" positions
586 * also, use a size of 9 like codeC above, as each symbol is
587 * represented by two chars
588 */
589 sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos,
590 code >= 100 ? 'A' : code/10 + '0',
591 textpos + (double)SYMBOL_WID/2, code%10 + '0');
592 textptr += strlen(textptr);
593 textpos += SYMBOL_WID; /* width of each code */
594 i += n;
595 }
596 /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
597 checksum %= 103;
598 strcat(partial, codeset[checksum]);
599 /* and the end marker */
600 strcat(partial, codeset[STOP]);
601
602 bc->partial = partial;
603 bc->textinfo = textinfo;
604
605 return 0;
606 }
607
608