gbarcode 0.98.16-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/COPYING +0 -0
- data/README +199 -0
- data/Rakefile +109 -0
- data/ext/barcode.h +119 -0
- data/ext/barcode_wrap.c +3192 -0
- data/ext/codabar.c +182 -0
- data/ext/code128.c +607 -0
- data/ext/code39.c +173 -0
- data/ext/code93.c +213 -0
- data/ext/ean.c +774 -0
- data/ext/extconf.rb +6 -0
- data/ext/i25.c +164 -0
- data/ext/library.c +244 -0
- data/ext/msi.c +155 -0
- data/ext/pcl.c +200 -0
- data/ext/plessey.c +164 -0
- data/ext/ps.c +272 -0
- data/ext/svg.c +174 -0
- data/extras/mingw-rbconfig.rb +176 -0
- data/lib/gbarcode.so +0 -0
- data/test/assets/gb-code128b.eps +44 -0
- data/test/gbarcode_test.rb +48 -0
- data/test/test_helper.rb +2 -0
- metadata +77 -0
data/ext/codabar.c
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
/*
|
2
|
+
* codabar.c -- encoding for Codabar
|
3
|
+
*
|
4
|
+
* Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
|
5
|
+
*
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
8
|
+
* the Free Software Foundation; either version 2 of the License, or
|
9
|
+
* (at your option) any later version.
|
10
|
+
*
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
* GNU General Public License for more details.
|
15
|
+
*
|
16
|
+
* You should have received a copy of the GNU General Public License
|
17
|
+
* along with this program; if not, write to the Free Software
|
18
|
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
19
|
+
*/
|
20
|
+
|
21
|
+
#include <stdio.h>
|
22
|
+
#include <stdlib.h>
|
23
|
+
#include <string.h>
|
24
|
+
#include <ctype.h>
|
25
|
+
#include <errno.h>
|
26
|
+
|
27
|
+
#include "barcode.h"
|
28
|
+
|
29
|
+
|
30
|
+
/* this is ordered in decades to simplify encoding */
|
31
|
+
static char alphabet[] =
|
32
|
+
"0123456789" "-$:/.+ABCD";
|
33
|
+
|
34
|
+
#define CODE_A 16
|
35
|
+
#define CODE_B 17
|
36
|
+
|
37
|
+
#define NARROW 12
|
38
|
+
#define WIDE 14
|
39
|
+
|
40
|
+
/* Patterns */
|
41
|
+
static char *patterns[] = {
|
42
|
+
"1111133","1111331","1113113","3311111","1131131",
|
43
|
+
"3111131","1311113","1311311","1331111","3113111",
|
44
|
+
"1113311","1133111","3111313","3131113","3131311",
|
45
|
+
"1131313","1133131","1313113","1113133","1113331" };
|
46
|
+
|
47
|
+
/*
|
48
|
+
* Check that the text can be encoded. Returns 0 or -1.
|
49
|
+
* If it's all lowecase convert to uppercase and accept it.
|
50
|
+
* If the first character is a letter (A to D), the last one must be too;
|
51
|
+
* no other character should be a letter.
|
52
|
+
*/
|
53
|
+
int Barcode_cbr_verify(unsigned char *text)
|
54
|
+
{
|
55
|
+
int i, lower=0, upper=0;
|
56
|
+
int startpresent = 0;
|
57
|
+
|
58
|
+
if (!strlen(text))
|
59
|
+
return -1;
|
60
|
+
for (i=0; text[i]; i++) {
|
61
|
+
char * pos;
|
62
|
+
if (isupper(text[i])) upper++;
|
63
|
+
if (islower(text[i])) lower++;
|
64
|
+
pos = strchr(alphabet,toupper(text[i]));
|
65
|
+
if (!pos)
|
66
|
+
return -1;
|
67
|
+
if (i == 0 && pos - alphabet >= CODE_A)
|
68
|
+
startpresent = 1;
|
69
|
+
else if (pos - alphabet >= CODE_A &&
|
70
|
+
(!startpresent || i != strlen(text) - 1))
|
71
|
+
return -1;
|
72
|
+
}
|
73
|
+
if (lower && upper)
|
74
|
+
return -1;
|
75
|
+
return 0;
|
76
|
+
}
|
77
|
+
|
78
|
+
static int add_one(char *ptr, int code)
|
79
|
+
{
|
80
|
+
sprintf(ptr,"1%s", /* separator */ patterns[code]);
|
81
|
+
return 0;
|
82
|
+
}
|
83
|
+
|
84
|
+
/*
|
85
|
+
* The encoding functions fills the "partial" and "textinfo" fields.
|
86
|
+
* Lowercase chars are converted to uppercase
|
87
|
+
*/
|
88
|
+
int Barcode_cbr_encode(struct Barcode_Item *bc)
|
89
|
+
{
|
90
|
+
static char *text;
|
91
|
+
static char *partial; /* dynamic */
|
92
|
+
static char *textinfo; /* dynamic */
|
93
|
+
char *c, *ptr, *textptr;
|
94
|
+
int i, code, textpos, usesum, checksum = 0, startpresent;
|
95
|
+
|
96
|
+
if (bc->partial)
|
97
|
+
free(bc->partial);
|
98
|
+
if (bc->textinfo)
|
99
|
+
free(bc->textinfo);
|
100
|
+
bc->partial = bc->textinfo = NULL; /* safe */
|
101
|
+
|
102
|
+
if (!bc->encoding)
|
103
|
+
bc->encoding = strdup("codabar");
|
104
|
+
|
105
|
+
text = bc->ascii;
|
106
|
+
if (!text) {
|
107
|
+
bc->error = EINVAL;
|
108
|
+
return -1;
|
109
|
+
}
|
110
|
+
/* the partial code is 8 * (head + text + check + tail) + margin + term. */
|
111
|
+
partial = malloc( (strlen(text) + 3) * 8 + 2);
|
112
|
+
if (!partial) {
|
113
|
+
bc->error = errno;
|
114
|
+
return -1;
|
115
|
+
}
|
116
|
+
|
117
|
+
/* the text information is at most "nnn:fff:c " * (strlen + check) +term */
|
118
|
+
textinfo = malloc(10*(strlen(text) + 1) + 2);
|
119
|
+
if (!textinfo) {
|
120
|
+
bc->error = errno;
|
121
|
+
free(partial);
|
122
|
+
return -1;
|
123
|
+
}
|
124
|
+
|
125
|
+
ptr = partial;
|
126
|
+
textptr = textinfo;
|
127
|
+
textpos = 0;
|
128
|
+
usesum = bc->flags & BARCODE_NO_CHECKSUM ? 0 : 1;
|
129
|
+
/* if no start character specified, A is used as a start character */
|
130
|
+
if (!isalpha(text[0])) {
|
131
|
+
add_one(ptr, CODE_A);
|
132
|
+
ptr += strlen(ptr);
|
133
|
+
textpos = WIDE;
|
134
|
+
checksum = CODE_A;
|
135
|
+
startpresent = 0;
|
136
|
+
} else {
|
137
|
+
startpresent = 1;
|
138
|
+
}
|
139
|
+
for (i=0; i<strlen(text); i++) {
|
140
|
+
c = strchr(alphabet, toupper(text[i]));
|
141
|
+
if (!c) {
|
142
|
+
bc->error = EINVAL; /* impossible if text is verified */
|
143
|
+
free(partial);
|
144
|
+
free(textinfo);
|
145
|
+
return -1;
|
146
|
+
}
|
147
|
+
code = c - alphabet;
|
148
|
+
add_one(ptr, code);
|
149
|
+
sprintf(textptr, "%i:12:%c ", textpos, toupper(text[i]));
|
150
|
+
textpos += code < 12 ? NARROW : WIDE;
|
151
|
+
textptr += strlen(textptr);
|
152
|
+
ptr += strlen(ptr);
|
153
|
+
checksum += code;
|
154
|
+
if (startpresent && usesum && i == strlen(text) - 2) {
|
155
|
+
/* stuff a check symbol before the stop */
|
156
|
+
c = strchr(alphabet, toupper(text[i+1]));
|
157
|
+
if (!c) /* impossible */
|
158
|
+
continue;
|
159
|
+
code = c - alphabet;
|
160
|
+
checksum += code;
|
161
|
+
|
162
|
+
/* Complement to a multiple of 16 */
|
163
|
+
checksum = (checksum + 15) / 16 * 16 - checksum;
|
164
|
+
add_one(ptr, checksum);
|
165
|
+
ptr += strlen(ptr);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
if (!startpresent) {
|
169
|
+
if (usesum) {
|
170
|
+
/* if no start character specified, B is used as a stop char */
|
171
|
+
checksum += CODE_B;
|
172
|
+
checksum = (checksum + 15) / 16 * 16 - checksum;
|
173
|
+
add_one(ptr, checksum);
|
174
|
+
ptr += strlen(ptr);
|
175
|
+
}
|
176
|
+
add_one(ptr, CODE_B);
|
177
|
+
}
|
178
|
+
bc->partial = partial;
|
179
|
+
bc->textinfo = textinfo;
|
180
|
+
|
181
|
+
return 0;
|
182
|
+
}
|
data/ext/code128.c
ADDED
@@ -0,0 +1,607 @@
|
|
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
|
+
|