comparison mupdf-source/thirdparty/zint/backend/upcean.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* upcean.c - Handles UPC, EAN and ISBN */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2008-2024 Robin Stuart <rstuart114@gmail.com>
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the project nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31 /* SPDX-License-Identifier: BSD-3-Clause */
32
33 #define SODIUM_PLS_F (IS_NUM_F | IS_PLS_F) /* SODIUM "0123456789+" */
34 #define ISBNX_SANE_F (IS_NUM_F | IS_UX__F) /* ISBNX_SANE "0123456789X" */
35 #define ISBNX_ADDON_SANE_F (IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F) /* ISBNX_ADDON_SANE "0123456789Xx+" */
36
37 #include <assert.h>
38 #include <stdio.h>
39 #include "common.h"
40 #include "gs1.h"
41
42 /* UPC and EAN tables checked against EN 797:1996 */
43
44 static const char UPCParity0[10][6] = {
45 /* Number set for UPC-E symbol (EN Table 4) */
46 {'B','B','B','A','A','A'}, {'B','B','A','B','A','A'}, {'B','B','A','A','B','A'}, {'B','B','A','A','A','B'},
47 {'B','A','B','B','A','A'}, {'B','A','A','B','B','A'}, {'B','A','A','A','B','B'}, {'B','A','B','A','B','A'},
48 {'B','A','B','A','A','B'}, {'B','A','A','B','A','B'}
49 };
50
51 static const char UPCParity1[10][6] = {
52 /* Not covered by BS EN 797:1995 */
53 {'A','A','A','B','B','B'}, {'A','A','B','A','B','B'}, {'A','A','B','B','A','B'}, {'A','A','B','B','B','A'},
54 {'A','B','A','A','B','B'}, {'A','B','B','A','A','B'}, {'A','B','B','B','A','A'}, {'A','B','A','B','A','B'},
55 {'A','B','A','B','B','A'}, {'A','B','B','A','B','A'}
56 };
57
58 static const char EAN2Parity[4][2] = {
59 /* Number sets for 2-digit add-on (EN Table 6) */
60 {'A','A'}, {'A','B'}, {'B','A'}, {'B','B'}
61 };
62
63 static const char EAN5Parity[10][5] = {
64 /* Number set for 5-digit add-on (EN Table 7) */
65 {'B','B','A','A','A'}, {'B','A','B','A','A'}, {'B','A','A','B','A'}, {'B','A','A','A','B'}, {'A','B','B','A','A'},
66 {'A','A','B','B','A'}, {'A','A','A','B','B'}, {'A','B','A','B','A'}, {'A','B','A','A','B'}, {'A','A','B','A','B'}
67 };
68
69 static const char EAN13Parity[10][5] = {
70 /* Left hand of the EAN-13 symbol (EN Table 3) */
71 {'A','A','A','A','A'}, {'A','B','A','B','B'}, {'A','B','B','A','B'}, {'A','B','B','B','A'}, {'B','A','A','B','B'},
72 {'B','B','A','A','B'}, {'B','B','B','A','A'}, {'B','A','B','A','B'}, {'B','A','B','B','A'}, {'B','B','A','B','A'}
73 };
74
75 static const char EANsetA[10][4] = {
76 /* Representation set A and C (EN Table 1) */
77 {'3','2','1','1'}, {'2','2','2','1'}, {'2','1','2','2'}, {'1','4','1','1'}, {'1','1','3','2'},
78 {'1','2','3','1'}, {'1','1','1','4'}, {'1','3','1','2'}, {'1','2','1','3'}, {'3','1','1','2'}
79 };
80
81 static const char EANsetB[10][4] = {
82 /* Representation set B (EN Table 1) */
83 {'1','1','2','3'}, {'1','2','2','2'}, {'2','2','1','2'}, {'1','1','4','1'}, {'2','3','1','1'},
84 {'1','3','2','1'}, {'4','1','1','1'}, {'2','1','3','1'}, {'3','1','2','1'}, {'2','1','1','3'}
85 };
86
87 /* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */
88 static void upca_draw(const unsigned char source[], const int length, char *d) {
89 int i, half_way;
90
91 half_way = length / 2;
92
93 /* start character */
94 memcpy(d, "111", 3);
95 d += 3;
96
97 for (i = 0; i < length; i++, d += 4) {
98 if (i == half_way) {
99 /* middle character - separates manufacturer no. from product no. */
100 /* also inverts right hand characters */
101 memcpy(d, "11111", 5);
102 d += 5;
103 }
104
105 memcpy(d, EANsetA[source[i] - '0'], 4);
106 }
107
108 /* stop character */
109 strcpy(d, "111");
110 }
111
112 /* Make a UPC-A barcode, allowing for composite if `cc_rows` set */
113 static int upca_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], int cc_rows) {
114 unsigned char *gtin = symbol->text;
115 int error_number = 0;
116
117 ustrcpy(gtin, source);
118
119 if (length == 11) {
120 gtin[length++] = gs1_check_digit(gtin, 11);
121 gtin[length] = '\0';
122 } else {
123 if (source[length - 1] != gs1_check_digit(gtin, 11)) {
124 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 270, "Invalid check digit '%1$c', expecting '%2$c'",
125 source[length - 1], gs1_check_digit(gtin, 11));
126 }
127 }
128 if (symbol->debug & ZINT_DEBUG_PRINT) {
129 printf("UPC-A: %s, gtin: %s, Check digit: %c\n", source, gtin,
130 length == 11 ? gtin[length] : gtin[length - 1]);
131 }
132
133 upca_draw(gtin, length, dest);
134
135 if (symbol->output_options & COMPLIANT_HEIGHT) {
136 /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24,
137 same as minimum GS1 General Specifications 21.0.1 5.12.3.1 */
138 const float height = 69.242424f; /* 22.85 / 0.33 */
139 if (symbol->symbology == BARCODE_UPCA_CC) {
140 symbol->height = height; /* Pass back min row == default height */
141 } else {
142 error_number = set_height(symbol, height, height, 0.0f, 0 /*no_errtxt*/);
143 }
144 } else {
145 const float height = 50.0f;
146 if (symbol->symbology == BARCODE_UPCA_CC) {
147 symbol->height = height - cc_rows * 2 - 6.0f;
148 } else {
149 (void) set_height(symbol, 0.0f, height, 0.0f, 1 /*no_errtxt*/);
150 }
151 }
152
153 return error_number;
154 }
155
156 /* UPC-A */
157 static int upca(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[]) {
158 return upca_cc(symbol, source, length, dest, 0 /*cc_rows*/);
159 }
160
161 /* UPC-E, allowing for composite if `cc_rows` set */
162 static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int length, char *d, int cc_rows) {
163 int i, num_system;
164 char emode, check_digit;
165 const char *parity;
166 char src_check_digit = '\0';
167 unsigned char equivalent[12];
168 unsigned char *hrt = symbol->text;
169 int error_number = 0;
170
171 if (length == 8 || symbol->symbology == BARCODE_UPCE_CHK) {
172 /* Will validate later */
173 src_check_digit = source[--length];
174 }
175
176 /* Two number systems can be used - system 0 and system 1 */
177 hrt[0] = '\0';
178 if (length == 7) {
179 switch (source[0]) {
180 case '0':
181 num_system = 0;
182 ustrncat(hrt, source, length);
183 break;
184 case '1':
185 num_system = 1;
186 ustrncat(hrt, source, length);
187 break;
188 default:
189 num_system = 0;
190 /* First source char ignored */
191 ustrncat(hrt, source, length);
192 hrt[0] = '0'; /* Overwrite HRT first char with '0' to correct TODO: error/warn in future */
193 break;
194 }
195 for (i = 1; i <= length; i++) {
196 source[i - 1] = hrt[i];
197 }
198 length--;
199 } else {
200 /* Length 6, insert leading zero */
201 num_system = 0;
202 hrt[0] = '0';
203 hrt[1] = '\0';
204 ustrncat(hrt, source, length);
205 }
206
207 /* Expand the zero-compressed UPCE code to make a UPCA equivalent (EN Table 5) */
208 emode = source[5];
209 for (i = 0; i < 11; i++) {
210 equivalent[i] = '0';
211 }
212 if (num_system == 1) {
213 equivalent[0] = hrt[0];
214 }
215 equivalent[1] = source[0];
216 equivalent[2] = source[1];
217 equivalent[11] = '\0';
218
219 switch (emode) {
220 case '0':
221 case '1':
222 case '2':
223 equivalent[3] = emode;
224 equivalent[8] = source[2];
225 equivalent[9] = source[3];
226 equivalent[10] = source[4];
227 break;
228 case '3':
229 equivalent[3] = source[2];
230 equivalent[9] = source[3];
231 equivalent[10] = source[4];
232 if (((source[2] == '0') || (source[2] == '1')) || (source[2] == '2')) {
233 /* Note 1 - "X3 shall not be equal to 0, 1 or 2" */
234 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 271,
235 "For this UPC-E zero suppression, 3rd character cannot be \"0\", \"1\" or \"2\" (%.*s)",
236 length, source);
237 }
238 break;
239 case '4':
240 equivalent[3] = source[2];
241 equivalent[4] = source[3];
242 equivalent[10] = source[4];
243 if (source[3] == '0') {
244 /* Note 2 - "X4 shall not be equal to 0" */
245 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 272,
246 "For this UPC-E zero suppression, 4th character cannot be \"0\" (%.*s)",
247 length, source);
248 }
249 break;
250 case '5':
251 case '6':
252 case '7':
253 case '8':
254 case '9':
255 equivalent[3] = source[2];
256 equivalent[4] = source[3];
257 equivalent[5] = source[4];
258 equivalent[10] = emode;
259 if (source[4] == '0') {
260 /* Note 3 - "X5 shall not be equal to 0" */
261 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 273,
262 "For this UPC-E zero suppression, 5th character cannot be \"0\" (%.*s)",
263 length, source);
264 }
265 break;
266 }
267
268 /* Get the check digit from the expanded UPCA code */
269
270 check_digit = gs1_check_digit(equivalent, 11);
271
272 if (src_check_digit && src_check_digit != check_digit) {
273 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 274, "Invalid check digit '%1$c', expecting '%2$c'",
274 src_check_digit, check_digit);
275 }
276
277 /* Use the number system and check digit information to choose a parity scheme */
278 if (num_system == 1) {
279 parity = UPCParity1[ctoi(check_digit)];
280 } else {
281 parity = UPCParity0[ctoi(check_digit)];
282 }
283
284 /* Take all this information and make the barcode pattern */
285
286 /* start character */
287 memcpy(d, "111", 3);
288 d += 3;
289
290 for (i = 0; i < length; i++, d += 4) {
291 switch (parity[i]) {
292 case 'A':
293 memcpy(d, EANsetA[source[i] - '0'], 4);
294 break;
295 case 'B':
296 memcpy(d, EANsetB[source[i] - '0'], 4);
297 break;
298 }
299 }
300
301 /* stop character */
302 strcpy(d, "111111");
303
304 hrt[7] = check_digit;
305 hrt[8] = '\0';
306
307 if (symbol->debug & ZINT_DEBUG_PRINT) {
308 printf("UPC-E: %s, equivalent: %s, hrt: %s, Check digit: %c\n", source, equivalent, hrt, check_digit);
309 }
310
311 if (symbol->output_options & COMPLIANT_HEIGHT) {
312 /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24,
313 same as minimum GS1 General Specifications 21.0.1 5.12.3.1 */
314 const float height = 69.242424f; /* 22.85 / 0.33 */
315 if (symbol->symbology == BARCODE_UPCE_CC) {
316 symbol->height = height; /* Pass back min row == default height */
317 } else {
318 error_number = set_height(symbol, height, height, 0.0f, 0 /*no_errtxt*/);
319 }
320 } else {
321 const float height = 50.0f;
322 if (symbol->symbology == BARCODE_UPCE_CC) {
323 symbol->height = height - cc_rows * 2 - 6.0f;
324 } else {
325 (void) set_height(symbol, 0.0f, height, 0.0f, 1 /*no_errtxt*/);
326 }
327 }
328
329 return error_number;
330 }
331
332 /* UPC-E is a zero-compressed version of UPC-A */
333 static int upce(struct zint_symbol *symbol, unsigned char source[], int length, char dest[]) {
334 return upce_cc(symbol, source, length, dest, 0 /*cc_rows*/);
335 }
336
337 /* EAN-2 and EAN-5 add-on codes */
338 static void ean_add_on(const unsigned char source[], const int length, char dest[], const int addon_gap) {
339 const char *parity;
340 int i;
341 char *d = dest + strlen(dest);
342
343 /* If an add-on then append with space */
344 if (addon_gap != 0) {
345 *d++ = itoc(addon_gap);
346 }
347
348 /* Start character */
349 memcpy(d, "112", 3);
350 d += 3;
351
352 /* Calculate parity */
353 if (length == 2) { /* EAN-2 */
354 int code_value, parity_bit;
355
356 code_value = (10 * ctoi(source[0])) + ctoi(source[1]);
357 parity_bit = code_value % 4;
358 parity = EAN2Parity[parity_bit];
359 } else { /* EAN-5 */
360 int values[6], parity_sum, parity_bit;
361
362 for (i = 0; i < 6; i++) {
363 values[i] = ctoi(source[i]);
364 }
365
366 parity_sum = (3 * (values[0] + values[2] + values[4]));
367 parity_sum += (9 * (values[1] + values[3]));
368
369 parity_bit = parity_sum % 10;
370 parity = EAN5Parity[parity_bit];
371 }
372
373 for (i = 0; i < length; i++) {
374 switch (parity[i]) {
375 case 'A':
376 memcpy(d, EANsetA[source[i] - '0'], 4);
377 d += 4;
378 break;
379 case 'B':
380 memcpy(d, EANsetB[source[i] - '0'], 4);
381 d += 4;
382 break;
383 }
384
385 /* Glyph separator */
386 if (i != (length - 1)) {
387 memcpy(d, "11", 2);
388 d += 2;
389 }
390 }
391 *d = '\0';
392 }
393
394 /* ************************ EAN-13 ****************** */
395
396 static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char *d,
397 int cc_rows) {
398 int i, half_way;
399 const char *parity;
400 unsigned char *gtin = symbol->text;
401 int error_number = 0;
402
403 ustrcpy(gtin, source);
404
405 /* Add the appropriate check digit */
406
407 if (length == 12) {
408 gtin[length++] = gs1_check_digit(gtin, 12);
409 gtin[length] = '\0';
410 } else {
411 if (source[length - 1] != gs1_check_digit(gtin, 12)) {
412 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 275, "Invalid check digit '%1$c', expecting '%2$c'",
413 source[length - 1], gs1_check_digit(gtin, 12));
414 }
415 }
416 if (symbol->debug & ZINT_DEBUG_PRINT) {
417 printf("EAN-13: %s, gtin: %s, Check digit: %c\n", source, gtin, gtin[length - 1]);
418 }
419
420 /* Get parity for first half of the symbol */
421 parity = EAN13Parity[gtin[0] - '0'];
422
423 /* Now get on with the cipher */
424 half_way = 7;
425
426 /* start character */
427 memcpy(d, "111", 3);
428 d += 3;
429
430 for (i = 1; i < length; i++, d += 4) {
431 if (i == half_way) {
432 /* middle character - separates manufacturer no. from product no. */
433 /* also inverses right hand characters */
434 memcpy(d, "11111", 5);
435 d += 5;
436 }
437
438 if (((i > 1) && (i < 7)) && (parity[i - 2] == 'B')) {
439 memcpy(d, EANsetB[gtin[i] - '0'], 4);
440 } else {
441 memcpy(d, EANsetA[gtin[i] - '0'], 4);
442 }
443 }
444
445 /* stop character */
446 strcpy(d, "111");
447
448 if (symbol->output_options & COMPLIANT_HEIGHT) {
449 /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24,
450 same as minimum GS1 General Specifications 21.0.1 5.12.3.1 */
451 const float height = 69.242424f; /* 22.85 / 0.33 */
452 if (symbol->symbology == BARCODE_EANX_CC) {
453 symbol->height = height; /* Pass back min row == default height */
454 } else {
455 error_number = set_height(symbol, height, height, 0.0f, 0 /*no_errtxt*/);
456 }
457 } else {
458 const float height = 50.0f;
459 if (symbol->symbology == BARCODE_EANX_CC) {
460 symbol->height = height - cc_rows * 2 - 6.0f;
461 } else {
462 (void) set_height(symbol, 0.0f, height, 0.0f, 1 /*no_errtxt*/);
463 }
464 }
465
466 return error_number;
467 }
468
469 static int ean13(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[]) {
470 return ean13_cc(symbol, source, length, dest, 0 /*cc_rows*/);
471 }
472
473 static int ean8_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], int cc_rows) {
474 /* EAN-8 is basically the same as UPC-A but with fewer digits */
475 unsigned char *gtin = symbol->text;
476 int error_number = 0;
477
478 ustrcpy(gtin, source);
479
480 if (length == 7) {
481 gtin[length++] = gs1_check_digit(gtin, 7);
482 gtin[length] = '\0';
483 } else {
484 if (source[length - 1] != gs1_check_digit(gtin, 7)) {
485 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 276, "Invalid check digit '%1$c', expecting '%2$c'",
486 source[length - 1], gs1_check_digit(gtin, 7));
487 }
488 }
489 if (symbol->debug & ZINT_DEBUG_PRINT) {
490 printf("EAN-8: %s, gtin: %s, Check digit: %c\n", source, gtin,
491 length == 7 ? gtin[length] : gtin[length - 1]);
492 }
493
494 upca_draw(gtin, length, dest);
495
496 if (symbol->output_options & COMPLIANT_HEIGHT) {
497 /* BS EN 797:1996 4.5.1 Nominal dimensions 18.23mm / 0.33mm (X) ~ 55.24,
498 same as minimum GS1 General Specifications 21.0.1 5.12.3.1 */
499 const float height = 55.242424f; /* 18.23 / 0.33 */
500 if (symbol->symbology == BARCODE_EANX_CC) {
501 symbol->height = height; /* Pass back min row == default height */
502 } else {
503 error_number = set_height(symbol, height, height, 0.0f, 0 /*no_errtxt*/);
504 }
505 } else {
506 const float height = 50.0f;
507 if (symbol->symbology == BARCODE_EANX_CC) {
508 symbol->height = height - cc_rows * 2 - 6.0f;
509 } else {
510 (void) set_height(symbol, 0.0f, height, 0.0f, 1 /*no_errtxt*/);
511 }
512 }
513
514 return error_number;
515 }
516
517 /* Make an EAN-8 barcode when we haven't been given the check digit */
518 static int ean8(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[]) {
519 return ean8_cc(symbol, source, length, dest, 0 /*cc_rows*/);
520 }
521
522 /* For ISBN(10) and SBN only */
523 static char isbnx_check(const unsigned char source[], const int length) {
524 int i, weight, sum, check;
525 char check_char;
526
527 sum = 0;
528 weight = 1;
529
530 for (i = 0; i < length; i++) { /* Length will always be 9 */
531 sum += ctoi(source[i]) * weight;
532 weight++;
533 }
534
535 check = sum % 11;
536 check_char = itoc(check);
537 if (check == 10) {
538 check_char = 'X';
539 }
540 return check_char;
541 }
542
543 /* Make an EAN-13 barcode from an SBN or ISBN */
544 static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int length, char dest[]) {
545 int i;
546 char check_digit;
547
548 to_upper(source, length);
549 if (not_sane(ISBNX_SANE_F, source, length)) { /* As source has been zero-padded, don't report position */
550 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 277, "Invalid character in input (digits and \"X\" only)");
551 }
552
553 /* Input must be 9, 10 or 13 characters */
554 if (length != 9 && length != 10 && length != 13) {
555 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 278, "Input length %d wrong (9, 10, or 13 only)", length);
556 }
557
558 if (length == 13) /* Using 13 character ISBN */ {
559 if (!(((source[0] == '9') && (source[1] == '7')) &&
560 ((source[2] == '8') || (source[2] == '9')))) {
561 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 279, "Invalid ISBN (must begin with \"978\" or \"979\")");
562 }
563
564 /* "X" cannot occur */
565 if (not_sane(NEON_F, source, 13)) {
566 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 282,
567 "Invalid character in input, \"X\" not allowed in ISBN-13");
568 }
569
570 check_digit = gs1_check_digit(source, 12);
571 if (source[12] != check_digit) {
572 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 280, "Invalid ISBN check digit '%1$c', expecting '%2$c'",
573 source[12], check_digit);
574 }
575 source[12] = '\0';
576
577 } else { /* Using 10 digit ISBN or 9 digit SBN padded with leading zero */
578 if (length == 9) /* Using 9 digit SBN */ {
579 /* Add leading zero */
580 for (i = 10; i > 0; i--) {
581 source[i] = source[i - 1];
582 }
583 source[0] = '0';
584 }
585
586 /* "X" can only occur in last position */
587 if (not_sane(NEON_F, source, 9)) {
588 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 296,
589 "Invalid character in input, \"X\" allowed in last position only");
590 }
591
592 check_digit = isbnx_check(source, 9);
593 if (check_digit != source[9]) {
594 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 281,
595 "Invalid %1$s check digit '%2$c', expecting '%3$c'", length == 9 ? "SBN" : "ISBN",
596 source[9], check_digit);
597 }
598 for (i = 11; i > 2; i--) { /* This drops the check digit */
599 source[i] = source[i - 3];
600 }
601 source[0] = '9';
602 source[1] = '7';
603 source[2] = '8';
604 source[12] = '\0';
605 }
606
607 return ean13(symbol, source, 12, dest);
608 }
609
610 /* Add leading zeroes to EAN and UPC strings */
611 INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[],
612 unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part,
613 unsigned char *zsecond_part) {
614 unsigned char first_part[14], second_part[6];
615 int with_addon = 0;
616 int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i, h;
617
618 h = (int) ustrlen(source);
619 for (i = 0; i < h; i++) {
620 if (source[i] == '+') {
621 with_addon = 1;
622 } else {
623 if (with_addon == 0) {
624 first_len++;
625 } else {
626 second_len++;
627 }
628 }
629 }
630 if (first_len > 13 || second_len > 5) {
631 if (first_len > 13) {
632 if (!second_len) {
633 errtxtf(0, symbol, 294, "Input length %d too long (maximum 13)", first_len);
634 } else {
635 errtxtf(0, symbol, 298, "Input EAN length %d too long (maximum 13)", first_len);
636 }
637 } else {
638 errtxtf(0, symbol, 297, "Input add-on length %d too long (maximum 5)", second_len);
639 }
640 if (p_with_addon) {
641 *p_with_addon = with_addon;
642 }
643 return 0;
644 }
645
646 /* Split input into two strings */
647 for (i = 0; i < first_len; i++) {
648 first_part[i] = source[i];
649 }
650 first_part[first_len] = '\0';
651
652 for (i = 0; i < second_len; i++) {
653 second_part[i] = source[i + first_len + 1];
654 }
655 second_part[second_len] = '\0';
656
657 /* Calculate target lengths */
658 if (second_len == 0) {
659 zsecond_len = 0;
660 } else if (second_len <= 2) {
661 zsecond_len = 2;
662 } else {
663 zsecond_len = 5;
664 }
665 switch (symbol->symbology) {
666 case BARCODE_EANX:
667 case BARCODE_EANX_CC:
668 if (first_len <= 12) {
669 if (first_len <= 7) {
670 zfirst_len = 7;
671 } else {
672 zfirst_len = 12;
673 }
674 }
675 if (second_len == 0 && symbol->symbology == BARCODE_EANX) { /* No composite EAN-2/5 */
676 if (first_len <= 5) {
677 if (first_len <= 2) {
678 zfirst_len = 2;
679 } else {
680 zfirst_len = 5;
681 }
682 }
683 }
684 break;
685 case BARCODE_EANX_CHK:
686 if (first_len <= 13) {
687 if (first_len <= 8) {
688 zfirst_len = 8;
689 } else {
690 zfirst_len = 13;
691 }
692 }
693 if (second_len == 0) {
694 if (first_len <= 5) {
695 if (first_len <= 2) {
696 zfirst_len = 2;
697 } else {
698 zfirst_len = 5;
699 }
700 }
701 }
702 break;
703 case BARCODE_UPCA:
704 case BARCODE_UPCA_CC:
705 zfirst_len = 11;
706 break;
707 case BARCODE_UPCA_CHK:
708 zfirst_len = 12;
709 break;
710 case BARCODE_UPCE:
711 case BARCODE_UPCE_CC:
712 if (first_len == 7) {
713 zfirst_len = 7;
714 } else if (first_len <= 6) {
715 zfirst_len = 6;
716 }
717 break;
718 case BARCODE_UPCE_CHK:
719 if (first_len == 8) {
720 zfirst_len = 8;
721 } else if (first_len <= 7) {
722 zfirst_len = 7;
723 }
724 break;
725 case BARCODE_ISBNX:
726 if (first_len <= 9) {
727 zfirst_len = 9;
728 }
729 break;
730 }
731
732 /* Copy adjusted data back to local_source */
733
734 /* Add leading zeroes */
735 for (i = 0; i < (zfirst_len - first_len); i++) {
736 local_source[i] = '0';
737 }
738 ustrcpy(local_source + i, first_part);
739 if (zfirst_part) {
740 ustrcpy(zfirst_part, local_source);
741 }
742
743 if (with_addon) {
744 h = (int) ustrlen(local_source);
745 local_source[h++] = '+';
746 for (i = 0; i < (zsecond_len - second_len); i++) {
747 local_source[h + i] = '0';
748 }
749 ustrcpy(local_source + h + i, second_part);
750 if (zsecond_part) {
751 ustrcpy(zsecond_part, local_source + h);
752 }
753 } else if (zsecond_part) {
754 *zsecond_part = '\0';
755 }
756
757 if (p_with_addon) {
758 *p_with_addon = with_addon;
759 }
760
761 return 1; /* Success */
762 }
763
764 INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, int cc_rows) {
765 unsigned char first_part[14], second_part[6];
766 unsigned char local_source[20]; /* Allow 13 + "+" + 5 + 1 */
767 char dest[1000] = {0};
768 int with_addon;
769 int error_number = 0, i, plus_count;
770 int addon_gap = 0;
771 int first_part_len, second_part_len;
772
773 if (length > 19) {
774 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 283, "Input length %d too long (maximum 19)", length);
775 }
776 if (symbol->symbology != BARCODE_ISBNX) {
777 /* ISBN has its own sanity routine */
778 if ((i = not_sane(SODIUM_PLS_F, source, length))) {
779 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 284,
780 "Invalid character at position %d in input (digits and \"+\" only)", i);
781 }
782 } else {
783 if ((i = not_sane(ISBNX_ADDON_SANE_F, source, length))) {
784 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 285,
785 "Invalid character at position %d in input (digits, \"X\" and \"+\" only)", i);
786 }
787 /* Add-on will be checked separately to be numeric only below */
788 }
789
790 /* Check for multiple '+' characters */
791 plus_count = 0;
792 for (i = 0; i < length; i++) {
793 if (source[i] == '+') {
794 plus_count++;
795 if (plus_count > 1) {
796 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 293, "Invalid add-on data (one \"+\" only)");
797 }
798 }
799 }
800
801 /* Add leading zeroes, checking max lengths of parts */
802 if (!ean_leading_zeroes(symbol, source, local_source, &with_addon, first_part, second_part)) {
803 return ZINT_ERROR_TOO_LONG; /* `ean_leading_zeroes()` sets `errtxt` */
804 }
805
806 if (with_addon) {
807 if (symbol->symbology == BARCODE_UPCA || symbol->symbology == BARCODE_UPCA_CHK
808 || symbol->symbology == BARCODE_UPCA_CC) {
809 addon_gap = symbol->option_2 >= 9 && symbol->option_2 <= 12 ? symbol->option_2 : 9;
810 } else {
811 addon_gap = symbol->option_2 >= 7 && symbol->option_2 <= 12 ? symbol->option_2 : 7;
812 }
813 }
814
815 first_part_len = (int) ustrlen(first_part);
816
817 switch (symbol->symbology) {
818 case BARCODE_EANX:
819 case BARCODE_EANX_CHK:
820 switch (first_part_len) {
821 case 2:
822 case 5:
823 ean_add_on(first_part, first_part_len, dest, 0);
824 ustrcpy(symbol->text, first_part);
825 if (symbol->output_options & COMPLIANT_HEIGHT) {
826 /* 21.9mm from GS1 General Specifications 5.2.6.6, Figure 5.2.6.6-6 */
827 const float height = 66.3636398f; /* 21.9 / 0.33 */
828 error_number = set_height(symbol, height, height, 0.0f, 0 /*no_errtxt*/);
829 } else {
830 (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/);
831 }
832 break;
833 case 7:
834 case 8:
835 error_number = ean8(symbol, first_part, first_part_len, dest);
836 break;
837 case 12:
838 case 13:
839 error_number = ean13(symbol, first_part, first_part_len, dest);
840 break;
841 default:
842 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 286,
843 "Input length %d wrong (2, 5, 7, 8, 12 or 13 only)", first_part_len);
844 break;
845 }
846 break;
847 case BARCODE_EANX_CC:
848 switch (first_part_len) { /* Adds vertical separator bars according to ISO/IEC 24723 section 11.4 */
849 case 7:
850 set_module(symbol, symbol->rows, 1);
851 set_module(symbol, symbol->rows, 67);
852 set_module(symbol, symbol->rows + 1, 0);
853 set_module(symbol, symbol->rows + 1, 68);
854 set_module(symbol, symbol->rows + 2, 1);
855 set_module(symbol, symbol->rows + 2, 67);
856 symbol->row_height[symbol->rows] = 2;
857 symbol->row_height[symbol->rows + 1] = 2;
858 symbol->row_height[symbol->rows + 2] = 2;
859 symbol->rows += 3;
860 error_number = ean8_cc(symbol, first_part, first_part_len, dest, cc_rows);
861 break;
862 case 12:
863 case 13:
864 set_module(symbol, symbol->rows, 1);
865 set_module(symbol, symbol->rows, 95);
866 set_module(symbol, symbol->rows + 1, 0);
867 set_module(symbol, symbol->rows + 1, 96);
868 set_module(symbol, symbol->rows + 2, 1);
869 set_module(symbol, symbol->rows + 2, 95);
870 symbol->row_height[symbol->rows] = 2;
871 symbol->row_height[symbol->rows + 1] = 2;
872 symbol->row_height[symbol->rows + 2] = 2;
873 symbol->rows += 3;
874 error_number = ean13_cc(symbol, first_part, first_part_len, dest, cc_rows);
875 break;
876 default:
877 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 287, "Input length %d wrong (7, 12 or 13 only)",
878 first_part_len);
879 break;
880 }
881 break;
882 case BARCODE_UPCA:
883 case BARCODE_UPCA_CHK:
884 if ((first_part_len == 11) || (first_part_len == 12)) {
885 error_number = upca(symbol, first_part, first_part_len, dest);
886 } else {
887 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 288, "Input length %d wrong (11 or 12 only)",
888 first_part_len);
889 }
890 break;
891 case BARCODE_UPCA_CC:
892 if (first_part_len == 11 || first_part_len == 12) {
893 set_module(symbol, symbol->rows, 1);
894 set_module(symbol, symbol->rows, 95);
895 set_module(symbol, symbol->rows + 1, 0);
896 set_module(symbol, symbol->rows + 1, 96);
897 set_module(symbol, symbol->rows + 2, 1);
898 set_module(symbol, symbol->rows + 2, 95);
899 symbol->row_height[symbol->rows] = 2;
900 symbol->row_height[symbol->rows + 1] = 2;
901 symbol->row_height[symbol->rows + 2] = 2;
902 symbol->rows += 3;
903 error_number = upca_cc(symbol, first_part, first_part_len, dest, cc_rows);
904 } else {
905 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 289, "Input length %d wrong (11 or 12 only)",
906 first_part_len);
907 }
908 break;
909 case BARCODE_UPCE:
910 case BARCODE_UPCE_CHK:
911 if ((first_part_len >= 6) && (first_part_len <= 8)) {
912 error_number = upce(symbol, first_part, first_part_len, dest);
913 } else {
914 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 290, "Input length %d wrong (6, 7 or 8 only)",
915 first_part_len);
916 }
917 break;
918 case BARCODE_UPCE_CC:
919 if ((first_part_len >= 6) && (first_part_len <= 8)) {
920 set_module(symbol, symbol->rows, 1);
921 set_module(symbol, symbol->rows, 51);
922 set_module(symbol, symbol->rows + 1, 0);
923 set_module(symbol, symbol->rows + 1, 52);
924 set_module(symbol, symbol->rows + 2, 1);
925 set_module(symbol, symbol->rows + 2, 51);
926 symbol->row_height[symbol->rows] = 2;
927 symbol->row_height[symbol->rows + 1] = 2;
928 symbol->row_height[symbol->rows + 2] = 2;
929 symbol->rows += 3;
930 error_number = upce_cc(symbol, first_part, first_part_len, dest, cc_rows);
931 } else {
932 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 291, "Input length %d wrong (6, 7 or 8 only)",
933 first_part_len);
934 }
935 break;
936 case BARCODE_ISBNX:
937 error_number = isbnx(symbol, first_part, first_part_len, dest);
938 break;
939 }
940
941 if (error_number >= ZINT_ERROR) {
942 return error_number;
943 }
944
945 second_part_len = (int) ustrlen(second_part);
946
947 if (symbol->symbology == BARCODE_ISBNX) { /* Need to further check that add-on numeric only */
948 if (not_sane(NEON_F, second_part, second_part_len)) {
949 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 295, "Invalid add-on data (digits only)");
950 }
951 }
952
953 if (second_part_len) {
954 ean_add_on(second_part, second_part_len, dest, addon_gap);
955 ustrcat(symbol->text, "+");
956 ustrcat(symbol->text, second_part);
957 }
958
959 expand(symbol, dest, (int) strlen(dest));
960
961 switch (symbol->symbology) {
962 case BARCODE_EANX_CC:
963 case BARCODE_UPCA_CC:
964 case BARCODE_UPCE_CC:
965 /* shift the symbol to the right one space to allow for separator bars */
966 for (i = (symbol->width + 1); i >= 1; i--) {
967 if (module_is_set(symbol, symbol->rows - 1, i - 1)) {
968 set_module(symbol, symbol->rows - 1, i);
969 } else {
970 unset_module(symbol, symbol->rows - 1, i);
971 }
972 }
973 unset_module(symbol, symbol->rows - 1, 0);
974 symbol->width += 1 + (second_part_len == 0); /* Only need right space if no add-on */
975 break;
976 }
977
978 return error_number;
979 }
980
981 /* Handle UPC, EAN, ISBN */
982 INTERNAL int eanx(struct zint_symbol *symbol, unsigned char source[], int length) {
983 return eanx_cc(symbol, source, length, 0 /*cc_rows*/);
984 }
985
986 /* vim: set ts=4 sw=4 et : */