Mercurial > hgrepos > Python2 > PyMuPDF
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 : */ |
