]> git.sur5r.net Git - glabels/blob - barcode-0.98/code128.c
Imported Upstream version 2.2.8
[glabels] / barcode-0.98 / code128.c
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
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
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
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
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
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
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 */
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
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  */
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
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
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