Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/composite.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 /* composite.c - Handles GS1 Composite Symbols */ | |
| 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 /* The functions "getBit", "init928" and "encode928" are copyright BSI and are | |
| 34 released with permission under the following terms: | |
| 35 | |
| 36 "Copyright subsists in all BSI publications. BSI also holds the copyright, in the | |
| 37 UK, of the international standardisation bodies. Except as | |
| 38 permitted under the Copyright, Designs and Patents Act 1988 no extract may be | |
| 39 reproduced, stored in a retrieval system or transmitted in any form or by any | |
| 40 means - electronic, photocopying, recording or otherwise - without prior written | |
| 41 permission from BSI. | |
| 42 | |
| 43 "This does not preclude the free use, in the course of implementing the standard, | |
| 44 of necessary details such as symbols, and size, type or grade designations. If these | |
| 45 details are to be used for any other purpose than implementation then the prior | |
| 46 written permission of BSI must be obtained." | |
| 47 | |
| 48 The date of publication for these functions is 31 May 2006 | |
| 49 */ | |
| 50 | |
| 51 #include <assert.h> | |
| 52 #include <math.h> | |
| 53 #include <stdio.h> | |
| 54 #include "common.h" | |
| 55 #include "pdf417.h" | |
| 56 #include "gs1.h" | |
| 57 #include "general_field.h" | |
| 58 | |
| 59 #include "composite.h" | |
| 60 | |
| 61 INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode, | |
| 62 const int cc_rows); | |
| 63 | |
| 64 INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); | |
| 65 INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], | |
| 66 unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part, | |
| 67 unsigned char *zsecond_part); | |
| 68 | |
| 69 INTERNAL int dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row); | |
| 70 INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); | |
| 71 INTERNAL int dbar_ltd_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); | |
| 72 INTERNAL int dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); | |
| 73 INTERNAL int dbar_date(const unsigned char source[], const int length, const int src_posn); | |
| 74 | |
| 75 static int cc_min(const int first, const int second) { | |
| 76 | |
| 77 if (first <= second) | |
| 78 return first; | |
| 79 else | |
| 80 return second; | |
| 81 } | |
| 82 | |
| 83 /* gets bit in bitString at bitPos */ | |
| 84 static int cc_getBit(const unsigned short *bitStr, const int bitPos) { | |
| 85 return !!(bitStr[bitPos >> 4] & (0x8000 >> (bitPos & 15))); | |
| 86 } | |
| 87 | |
| 88 /* converts bit string to base 928 values, codeWords[0] is highest order */ | |
| 89 static int cc_encode928(const unsigned short bitString[], unsigned short codeWords[], const int bitLng) { | |
| 90 int i, j, b, cwNdx, cwLng; | |
| 91 for (cwNdx = cwLng = b = 0; b < bitLng; b += 69, cwNdx += 7) { | |
| 92 const int bitCnt = cc_min(bitLng - b, 69); | |
| 93 int cwCnt; | |
| 94 cwLng += cwCnt = bitCnt / 10 + 1; | |
| 95 for (i = 0; i < cwCnt; i++) | |
| 96 codeWords[cwNdx + i] = 0; /* init 0 */ | |
| 97 for (i = 0; i < bitCnt; i++) { | |
| 98 if (cc_getBit(bitString, b + bitCnt - i - 1)) { | |
| 99 for (j = 0; j < cwCnt; j++) | |
| 100 codeWords[cwNdx + j] += cc_pwr928[i][j + 7 - cwCnt]; | |
| 101 } | |
| 102 } | |
| 103 for (i = cwCnt - 1; i > 0; i--) { | |
| 104 /* add "carries" */ | |
| 105 codeWords[cwNdx + i - 1] += codeWords[cwNdx + i] / 928; | |
| 106 codeWords[cwNdx + i] %= 928; | |
| 107 } | |
| 108 } | |
| 109 return (cwLng); | |
| 110 } | |
| 111 | |
| 112 /* CC-A 2D component */ | |
| 113 static void cc_a(struct zint_symbol *symbol, const char source[], const int cc_width) { | |
| 114 int i, segment, bitlen, cwCnt, variant, rows; | |
| 115 int k, offset, j, total, rsCodeWords[8] = {0}; | |
| 116 int LeftRAPStart, RightRAPStart, CentreRAPStart, StartCluster; | |
| 117 int LeftRAP, RightRAP, CentreRAP, Cluster; | |
| 118 int loop; | |
| 119 unsigned short codeWords[28] = {0}; | |
| 120 unsigned short bitStr[13] = {0}; | |
| 121 char pattern[580]; | |
| 122 int bp = 0; | |
| 123 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 124 | |
| 125 variant = 0; | |
| 126 | |
| 127 bitlen = (int) strlen(source); | |
| 128 | |
| 129 for (segment = 0; segment < 13; segment++) { | |
| 130 const int strpos = segment * 16; | |
| 131 if (strpos >= bitlen) { | |
| 132 break; | |
| 133 } | |
| 134 for (i = 0; i < 16 && strpos + i < bitlen; i++) { | |
| 135 if (source[strpos + i] == '1') { | |
| 136 bitStr[segment] |= (0x8000 >> i); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 /* encode codeWords from bitStr */ | |
| 142 cwCnt = cc_encode928(bitStr, codeWords, bitlen); | |
| 143 | |
| 144 switch (cc_width) { | |
| 145 case 2: | |
| 146 switch (cwCnt) { | |
| 147 case 6: variant = 0; | |
| 148 break; | |
| 149 case 8: variant = 1; | |
| 150 break; | |
| 151 case 9: variant = 2; | |
| 152 break; | |
| 153 case 11: variant = 3; | |
| 154 break; | |
| 155 case 12: variant = 4; | |
| 156 break; | |
| 157 case 14: variant = 5; | |
| 158 break; | |
| 159 case 17: variant = 6; | |
| 160 break; | |
| 161 } | |
| 162 break; | |
| 163 case 3: | |
| 164 switch (cwCnt) { | |
| 165 case 8: variant = 7; | |
| 166 break; | |
| 167 case 10: variant = 8; | |
| 168 break; | |
| 169 case 12: variant = 9; | |
| 170 break; | |
| 171 case 14: variant = 10; | |
| 172 break; | |
| 173 case 17: variant = 11; | |
| 174 break; | |
| 175 } | |
| 176 break; | |
| 177 case 4: | |
| 178 switch (cwCnt) { | |
| 179 case 8: variant = 12; | |
| 180 break; | |
| 181 case 11: variant = 13; | |
| 182 break; | |
| 183 case 14: variant = 14; | |
| 184 break; | |
| 185 case 17: variant = 15; | |
| 186 break; | |
| 187 case 20: variant = 16; | |
| 188 break; | |
| 189 } | |
| 190 break; | |
| 191 } | |
| 192 | |
| 193 rows = cc_aVariants[variant]; | |
| 194 k = cc_aVariants[17 + variant]; | |
| 195 offset = cc_aVariants[34 + variant]; | |
| 196 | |
| 197 /* Reed-Solomon error correction */ | |
| 198 | |
| 199 for (i = 0; i < cwCnt; i++) { | |
| 200 total = (codeWords[i] + rsCodeWords[k - 1]) % 929; | |
| 201 for (j = k - 1; j >= 0; j--) { | |
| 202 if (j == 0) { | |
| 203 rsCodeWords[j] = (929 - (total * cc_aCoeffs[offset + j]) % 929) % 929; | |
| 204 } else { | |
| 205 rsCodeWords[j] = (rsCodeWords[j - 1] + 929 - (total * cc_aCoeffs[offset + j]) % 929) % 929; | |
| 206 } | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 for (j = 0; j < k; j++) { | |
| 211 if (rsCodeWords[j] != 0) { | |
| 212 rsCodeWords[j] = 929 - rsCodeWords[j]; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 for (i = k - 1; i >= 0; i--) { | |
| 217 codeWords[cwCnt] = rsCodeWords[i]; | |
| 218 cwCnt++; | |
| 219 } | |
| 220 | |
| 221 /* Place data into table */ | |
| 222 LeftRAPStart = cc_aRAPTable[variant]; | |
| 223 CentreRAPStart = cc_aRAPTable[variant + 17]; | |
| 224 RightRAPStart = cc_aRAPTable[variant + 34]; | |
| 225 StartCluster = cc_aRAPTable[variant + 51] / 3; | |
| 226 | |
| 227 LeftRAP = LeftRAPStart; | |
| 228 CentreRAP = CentreRAPStart; | |
| 229 RightRAP = RightRAPStart; | |
| 230 Cluster = StartCluster; /* Cluster can be 0, 1 or 2 for Cluster(0), Cluster(3) and Cluster(6) */ | |
| 231 | |
| 232 for (i = 0; i < rows; i++) { | |
| 233 bp = 0; | |
| 234 offset = 929 * Cluster; | |
| 235 k = i * cc_width; | |
| 236 /* Copy the data into codebarre */ | |
| 237 if (cc_width != 3) { | |
| 238 bp = bin_append_posn(pdf_rap_side[LeftRAP - 1], 10, pattern, bp); | |
| 239 } | |
| 240 bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k]], 16, pattern, bp); | |
| 241 pattern[bp++] = '0'; | |
| 242 if (cc_width >= 2) { | |
| 243 if (cc_width == 3) { | |
| 244 bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp); | |
| 245 } | |
| 246 bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 1]], 16, pattern, bp); | |
| 247 pattern[bp++] = '0'; | |
| 248 if (cc_width >= 3) { | |
| 249 if (cc_width == 4) { | |
| 250 bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp); | |
| 251 } | |
| 252 bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 2]], 16, pattern, bp); | |
| 253 pattern[bp++] = '0'; | |
| 254 if (cc_width == 4) { | |
| 255 bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 3]], 16, pattern, bp); | |
| 256 pattern[bp++] = '0'; | |
| 257 } | |
| 258 } | |
| 259 } | |
| 260 bp = bin_append_posn(pdf_rap_side[RightRAP - 1], 10, pattern, bp); | |
| 261 pattern[bp++] = '1'; /* stop */ | |
| 262 | |
| 263 /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */ | |
| 264 for (loop = 0; loop < bp; loop++) { | |
| 265 if (pattern[loop] == '1') { | |
| 266 set_module(symbol, i, loop); | |
| 267 } | |
| 268 } | |
| 269 symbol->row_height[i] = 2; | |
| 270 symbol->rows++; | |
| 271 | |
| 272 /* Set up RAPs and Cluster for next row */ | |
| 273 LeftRAP++; | |
| 274 CentreRAP++; | |
| 275 RightRAP++; | |
| 276 Cluster++; | |
| 277 | |
| 278 if (LeftRAP == 53) { | |
| 279 LeftRAP = 1; | |
| 280 } | |
| 281 if (CentreRAP == 53) { | |
| 282 CentreRAP = 1; | |
| 283 } | |
| 284 if (RightRAP == 53) { | |
| 285 RightRAP = 1; | |
| 286 } | |
| 287 if (Cluster == 3) { | |
| 288 Cluster = 0; | |
| 289 } | |
| 290 } | |
| 291 symbol->width = bp; | |
| 292 | |
| 293 if (debug_print) { | |
| 294 printf("CC-A Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n", cc_width, symbol->rows, variant, cwCnt); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 /* CC-B 2D component */ | |
| 299 static void cc_b(struct zint_symbol *symbol, const char source[], const int cc_width) { | |
| 300 const int length = (int) strlen(source) / 8; | |
| 301 int i; | |
| 302 unsigned char *data_string = (unsigned char *) z_alloca(length + 3); | |
| 303 short chainemc[180]; | |
| 304 int mclength = 0; | |
| 305 int k, j, p, longueur, mccorrection[50] = {0}, offset; | |
| 306 int total; | |
| 307 char pattern[580]; | |
| 308 int variant, LeftRAPStart, CentreRAPStart, RightRAPStart, StartCluster; | |
| 309 int LeftRAP, CentreRAP, RightRAP, Cluster, loop; | |
| 310 int columns; | |
| 311 int bp = 0; | |
| 312 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 313 | |
| 314 for (i = 0; i < length; i++) { | |
| 315 const int binloc = i * 8; | |
| 316 | |
| 317 data_string[i] = 0; | |
| 318 for (p = 0; p < 8; p++) { | |
| 319 if (source[binloc + p] == '1') { | |
| 320 data_string[i] |= (0x80 >> p); | |
| 321 } | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 /* "the CC-B component shall have codeword 920 in the first symbol character position" (section 9a) */ | |
| 326 chainemc[mclength++] = 920; | |
| 327 | |
| 328 pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0); | |
| 329 | |
| 330 /* Now figure out which variant of the symbol to use and load values accordingly */ | |
| 331 | |
| 332 variant = 0; | |
| 333 | |
| 334 if (cc_width == 2) { | |
| 335 if (mclength <= 8) { | |
| 336 variant = 7; | |
| 337 } else if (mclength <= 13) { | |
| 338 variant = 8; | |
| 339 } else if (mclength <= 19) { | |
| 340 variant = 9; | |
| 341 } else if (mclength <= 24) { | |
| 342 variant = 10; | |
| 343 } else if (mclength <= 29) { | |
| 344 variant = 11; | |
| 345 } else if (mclength <= 33) { | |
| 346 variant = 12; | |
| 347 } else { | |
| 348 variant = 13; | |
| 349 } | |
| 350 } else if (cc_width == 3) { | |
| 351 if (mclength <= 6) { | |
| 352 variant = 14; | |
| 353 } else if (mclength <= 10) { | |
| 354 variant = 15; | |
| 355 } else if (mclength <= 14) { | |
| 356 variant = 16; | |
| 357 } else if (mclength <= 18) { | |
| 358 variant = 17; | |
| 359 } else if (mclength <= 24) { | |
| 360 variant = 18; | |
| 361 } else if (mclength <= 34) { | |
| 362 variant = 19; | |
| 363 } else if (mclength <= 46) { | |
| 364 variant = 20; | |
| 365 } else if (mclength <= 58) { | |
| 366 variant = 21; | |
| 367 } else if (mclength <= 70) { | |
| 368 variant = 22; | |
| 369 } else { | |
| 370 variant = 23; | |
| 371 } | |
| 372 } else if (cc_width == 4) { | |
| 373 if (mclength <= 8) { | |
| 374 variant = 24; | |
| 375 } else if (mclength <= 12) { | |
| 376 variant = 25; | |
| 377 } else if (mclength <= 18) { | |
| 378 variant = 26; | |
| 379 } else if (mclength <= 24) { | |
| 380 variant = 27; | |
| 381 } else if (mclength <= 30) { | |
| 382 variant = 28; | |
| 383 } else if (mclength <= 39) { | |
| 384 variant = 29; | |
| 385 } else if (mclength <= 54) { | |
| 386 variant = 30; | |
| 387 } else if (mclength <= 72) { | |
| 388 variant = 31; | |
| 389 } else if (mclength <= 90) { | |
| 390 variant = 32; | |
| 391 } else if (mclength <= 108) { | |
| 392 variant = 33; | |
| 393 } else { | |
| 394 variant = 34; | |
| 395 } | |
| 396 } | |
| 397 | |
| 398 /* Now we have the variant we can load the data - from here on the same as MicroPDF417 code */ | |
| 399 variant--; | |
| 400 assert(variant >= 0); | |
| 401 columns = pdf_MicroVariants[variant]; /* columns */ | |
| 402 symbol->rows = pdf_MicroVariants[variant + 34]; /* rows */ | |
| 403 k = pdf_MicroVariants[variant + 68]; /* number of EC CWs */ | |
| 404 longueur = (columns * symbol->rows) - k; /* number of non-EC CWs */ | |
| 405 i = longueur - mclength; /* amount of padding required */ | |
| 406 offset = pdf_MicroVariants[variant + 102]; /* coefficient offset */ | |
| 407 | |
| 408 /* Binary input padded to target length so no padding should be necessary */ | |
| 409 while (i > 0) { | |
| 410 chainemc[mclength++] = 900; /* Not reached */ | |
| 411 i--; | |
| 412 } | |
| 413 | |
| 414 /* Reed-Solomon error correction */ | |
| 415 longueur = mclength; | |
| 416 for (i = 0; i < longueur; i++) { | |
| 417 total = (chainemc[i] + mccorrection[k - 1]) % 929; | |
| 418 for (j = k - 1; j >= 0; j--) { | |
| 419 if (j == 0) { | |
| 420 mccorrection[j] = (929 - (total * pdf_Microcoeffs[offset + j]) % 929) % 929; | |
| 421 } else { | |
| 422 mccorrection[j] = (mccorrection[j - 1] + 929 - (total * pdf_Microcoeffs[offset + j]) % 929) % 929; | |
| 423 } | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 for (j = 0; j < k; j++) { | |
| 428 if (mccorrection[j] != 0) { | |
| 429 mccorrection[j] = 929 - mccorrection[j]; | |
| 430 } | |
| 431 } | |
| 432 /* we add these codes to the string */ | |
| 433 for (i = k - 1; i >= 0; i--) { | |
| 434 chainemc[mclength++] = mccorrection[i]; | |
| 435 } | |
| 436 | |
| 437 /* Now get the RAP (Row Address Pattern) start values */ | |
| 438 LeftRAPStart = pdf_RAPTable[variant]; | |
| 439 CentreRAPStart = pdf_RAPTable[variant + 34]; | |
| 440 RightRAPStart = pdf_RAPTable[variant + 68]; | |
| 441 StartCluster = pdf_RAPTable[variant + 102] / 3; | |
| 442 | |
| 443 /* That's all values loaded, get on with the encoding */ | |
| 444 | |
| 445 LeftRAP = LeftRAPStart; | |
| 446 CentreRAP = CentreRAPStart; | |
| 447 RightRAP = RightRAPStart; | |
| 448 Cluster = StartCluster; | |
| 449 /* Cluster can be 0, 1 or 2 for Cluster(0), Cluster(3) and Cluster(6) */ | |
| 450 | |
| 451 for (i = 0; i < symbol->rows; i++) { | |
| 452 bp = 0; | |
| 453 offset = 929 * Cluster; | |
| 454 k = i * columns; | |
| 455 /* Copy the data into codebarre */ | |
| 456 bp = bin_append_posn(pdf_rap_side[LeftRAP - 1], 10, pattern, bp); | |
| 457 bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k]], 16, pattern, bp); | |
| 458 pattern[bp++] = '0'; | |
| 459 if (cc_width >= 2) { | |
| 460 if (cc_width == 3) { | |
| 461 bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp); | |
| 462 } | |
| 463 bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 1]], 16, pattern, bp); | |
| 464 pattern[bp++] = '0'; | |
| 465 if (cc_width >= 3) { | |
| 466 if (cc_width == 4) { | |
| 467 bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp); | |
| 468 } | |
| 469 bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 2]], 16, pattern, bp); | |
| 470 pattern[bp++] = '0'; | |
| 471 if (cc_width == 4) { | |
| 472 bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 3]], 16, pattern, bp); | |
| 473 pattern[bp++] = '0'; | |
| 474 } | |
| 475 } | |
| 476 } | |
| 477 bp = bin_append_posn(pdf_rap_side[RightRAP - 1], 10, pattern, bp); | |
| 478 pattern[bp++] = '1'; /* stop */ | |
| 479 | |
| 480 /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */ | |
| 481 for (loop = 0; loop < bp; loop++) { | |
| 482 if (pattern[loop] == '1') { | |
| 483 set_module(symbol, i, loop); | |
| 484 } | |
| 485 } | |
| 486 symbol->row_height[i] = 2; | |
| 487 | |
| 488 /* Set up RAPs and Cluster for next row */ | |
| 489 LeftRAP++; | |
| 490 CentreRAP++; | |
| 491 RightRAP++; | |
| 492 Cluster++; | |
| 493 | |
| 494 if (LeftRAP == 53) { | |
| 495 LeftRAP = 1; | |
| 496 } | |
| 497 if (CentreRAP == 53) { | |
| 498 CentreRAP = 1; | |
| 499 } | |
| 500 if (RightRAP == 53) { | |
| 501 RightRAP = 1; | |
| 502 } | |
| 503 if (Cluster == 3) { | |
| 504 Cluster = 0; | |
| 505 } | |
| 506 } | |
| 507 symbol->width = bp; | |
| 508 | |
| 509 if (debug_print) { | |
| 510 printf("CC-B Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n", | |
| 511 cc_width, symbol->rows, variant + 1, mclength); | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 /* CC-C 2D component - byte compressed PDF417 */ | |
| 516 static void cc_c(struct zint_symbol *symbol, const char source[], const int cc_width, const int ecc_level) { | |
| 517 const int length = (int) strlen(source) / 8; | |
| 518 int i, p; | |
| 519 unsigned char *data_string = (unsigned char *) z_alloca(length + 4); | |
| 520 short chainemc[1000]; | |
| 521 int mclength = 0, k; | |
| 522 int offset, longueur, loop, total, j, mccorrection[520] = {0}; | |
| 523 int c1, c2, c3, dummy[35]; | |
| 524 char pattern[580]; | |
| 525 int bp = 0; | |
| 526 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 527 | |
| 528 for (i = 0; i < length; i++) { | |
| 529 const int binloc = i * 8; | |
| 530 | |
| 531 data_string[i] = 0; | |
| 532 for (p = 0; p < 8; p++) { | |
| 533 if (source[binloc + p] == '1') { | |
| 534 data_string[i] |= (0x80 >> p); | |
| 535 } | |
| 536 } | |
| 537 } | |
| 538 | |
| 539 chainemc[mclength++] = 0; /* space for length descriptor */ | |
| 540 chainemc[mclength++] = 920; /* CC-C identifier */ | |
| 541 | |
| 542 pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0); | |
| 543 | |
| 544 chainemc[0] = mclength; | |
| 545 | |
| 546 if (debug_print) { | |
| 547 printf("CC-C Codewords (%d):", mclength); | |
| 548 for (i = 0; i < mclength; i++) printf(" %d", chainemc[i]); | |
| 549 fputc('\n', stdout); | |
| 550 } | |
| 551 | |
| 552 k = 1; | |
| 553 for (i = 1; i <= (ecc_level + 1); i++) { | |
| 554 k *= 2; | |
| 555 } | |
| 556 | |
| 557 /* 796 - we now take care of the Reed Solomon codes */ | |
| 558 switch (ecc_level) { | |
| 559 case 1: offset = 2; /* Not reached */ | |
| 560 break; | |
| 561 case 2: offset = 6; /* Min ECC currently used is 2 */ | |
| 562 break; | |
| 563 case 3: offset = 14; | |
| 564 break; | |
| 565 case 4: offset = 30; | |
| 566 break; | |
| 567 case 5: offset = 62; /* Max ECC currently used is 5 */ | |
| 568 break; | |
| 569 case 6: offset = 126; /* Not reached */ | |
| 570 break; | |
| 571 case 7: offset = 254; /* Not reached */ | |
| 572 break; | |
| 573 case 8: offset = 510; /* Not reached */ | |
| 574 break; | |
| 575 default: offset = 0; /* Not reached */ | |
| 576 break; | |
| 577 } | |
| 578 | |
| 579 longueur = mclength; | |
| 580 for (i = 0; i < longueur; i++) { | |
| 581 total = (chainemc[i] + mccorrection[k - 1]) % 929; | |
| 582 for (j = k - 1; j >= 0; j--) { | |
| 583 if (j == 0) { | |
| 584 mccorrection[j] = (929 - (total * pdf_coefrs[offset + j]) % 929) % 929; | |
| 585 } else { | |
| 586 mccorrection[j] = (mccorrection[j - 1] + 929 - (total * pdf_coefrs[offset + j]) % 929) % 929; | |
| 587 } | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 for (j = 0; j < k; j++) { | |
| 592 if (mccorrection[j] != 0) { | |
| 593 mccorrection[j] = 929 - mccorrection[j]; | |
| 594 } | |
| 595 } | |
| 596 /* we add these codes to the string */ | |
| 597 for (i = k - 1; i >= 0; i--) { | |
| 598 chainemc[mclength++] = mccorrection[i]; | |
| 599 } | |
| 600 | |
| 601 /* 818 - The CW string is finished */ | |
| 602 symbol->rows = mclength / cc_width; | |
| 603 c1 = (symbol->rows - 1) / 3; | |
| 604 c2 = ecc_level * 3 + (symbol->rows - 1) % 3; | |
| 605 c3 = cc_width - 1; | |
| 606 | |
| 607 /* we now encode each row */ | |
| 608 for (i = 0; i <= symbol->rows - 1; i++) { | |
| 609 for (j = 0; j < cc_width; j++) { | |
| 610 dummy[j + 1] = chainemc[i * cc_width + j]; | |
| 611 } | |
| 612 k = (i / 3) * 30; | |
| 613 switch (i % 3) { | |
| 614 case 0: | |
| 615 dummy[0] = k + c1; | |
| 616 dummy[cc_width + 1] = k + c3; | |
| 617 offset = 0; /* cluster(0) */ | |
| 618 break; | |
| 619 case 1: | |
| 620 dummy[0] = k + c2; | |
| 621 dummy[cc_width + 1] = k + c1; | |
| 622 offset = 929; /* cluster(3) */ | |
| 623 break; | |
| 624 case 2: | |
| 625 dummy[0] = k + c3; | |
| 626 dummy[cc_width + 1] = k + c2; | |
| 627 offset = 1858; /* cluster(6) */ | |
| 628 break; | |
| 629 } | |
| 630 bp = 0; | |
| 631 bp = bin_append_posn(0x1FEA8, 17, pattern, bp); /* Row start */ | |
| 632 | |
| 633 for (j = 0; j <= cc_width + 1; j++) { | |
| 634 bp = bin_append_posn(pdf_bitpattern[offset + dummy[j]], 16, pattern, bp); | |
| 635 pattern[bp++] = '0'; | |
| 636 } | |
| 637 bp = bin_append_posn(0x3FA29, 18, pattern, bp); /* Row Stop */ | |
| 638 | |
| 639 for (loop = 0; loop < bp; loop++) { | |
| 640 if (pattern[loop] == '1') { | |
| 641 set_module(symbol, i, loop); | |
| 642 } | |
| 643 } | |
| 644 symbol->row_height[i] = 3; | |
| 645 } | |
| 646 symbol->width = bp; | |
| 647 | |
| 648 if (debug_print) { | |
| 649 printf("CC-C Columns: %d, Rows: %d, CodeWords: %d, ECC Level: %d\n", | |
| 650 cc_width, symbol->rows, mclength, ecc_level); | |
| 651 } | |
| 652 } | |
| 653 | |
| 654 static int cc_a_calc_padding(const int binary_length, const int cc_width) { | |
| 655 int target_bitsize = 0; | |
| 656 | |
| 657 switch (cc_width) { | |
| 658 case 2: | |
| 659 if (binary_length <= 59) { | |
| 660 target_bitsize = 59; | |
| 661 } else if (binary_length <= 78) { | |
| 662 target_bitsize = 78; | |
| 663 } else if (binary_length <= 88) { | |
| 664 target_bitsize = 88; | |
| 665 } else if (binary_length <= 108) { | |
| 666 target_bitsize = 108; | |
| 667 } else if (binary_length <= 118) { | |
| 668 target_bitsize = 118; | |
| 669 } else if (binary_length <= 138) { | |
| 670 target_bitsize = 138; | |
| 671 } else if (binary_length <= 167) { | |
| 672 target_bitsize = 167; | |
| 673 } | |
| 674 break; | |
| 675 case 3: | |
| 676 if (binary_length <= 78) { | |
| 677 target_bitsize = 78; | |
| 678 } else if (binary_length <= 98) { | |
| 679 target_bitsize = 98; | |
| 680 } else if (binary_length <= 118) { | |
| 681 target_bitsize = 118; | |
| 682 } else if (binary_length <= 138) { | |
| 683 target_bitsize = 138; | |
| 684 } else if (binary_length <= 167) { | |
| 685 target_bitsize = 167; | |
| 686 } | |
| 687 break; | |
| 688 case 4: | |
| 689 if (binary_length <= 78) { | |
| 690 target_bitsize = 78; | |
| 691 } else if (binary_length <= 108) { | |
| 692 target_bitsize = 108; | |
| 693 } else if (binary_length <= 138) { | |
| 694 target_bitsize = 138; | |
| 695 } else if (binary_length <= 167) { | |
| 696 target_bitsize = 167; | |
| 697 } else if (binary_length <= 197) { | |
| 698 target_bitsize = 197; | |
| 699 } | |
| 700 break; | |
| 701 } | |
| 702 | |
| 703 return target_bitsize; | |
| 704 } | |
| 705 | |
| 706 static int cc_b_calc_padding(const int binary_length, const int cc_width) { | |
| 707 int target_bitsize = 0; | |
| 708 | |
| 709 switch (cc_width) { | |
| 710 case 2: | |
| 711 if (binary_length <= 56) { | |
| 712 target_bitsize = 56; | |
| 713 } else if (binary_length <= 104) { | |
| 714 target_bitsize = 104; | |
| 715 } else if (binary_length <= 160) { | |
| 716 target_bitsize = 160; | |
| 717 } else if (binary_length <= 208) { | |
| 718 target_bitsize = 208; | |
| 719 } else if (binary_length <= 256) { | |
| 720 target_bitsize = 256; | |
| 721 } else if (binary_length <= 296) { | |
| 722 target_bitsize = 296; | |
| 723 } else if (binary_length <= 336) { | |
| 724 target_bitsize = 336; | |
| 725 } | |
| 726 break; | |
| 727 case 3: | |
| 728 if (binary_length <= 32) { | |
| 729 target_bitsize = 32; | |
| 730 } else if (binary_length <= 72) { | |
| 731 target_bitsize = 72; | |
| 732 } else if (binary_length <= 112) { | |
| 733 target_bitsize = 112; | |
| 734 } else if (binary_length <= 152) { | |
| 735 target_bitsize = 152; | |
| 736 } else if (binary_length <= 208) { | |
| 737 target_bitsize = 208; | |
| 738 } else if (binary_length <= 304) { | |
| 739 target_bitsize = 304; | |
| 740 } else if (binary_length <= 416) { | |
| 741 target_bitsize = 416; | |
| 742 } else if (binary_length <= 536) { | |
| 743 target_bitsize = 536; | |
| 744 } else if (binary_length <= 648) { | |
| 745 target_bitsize = 648; | |
| 746 } else if (binary_length <= 768) { | |
| 747 target_bitsize = 768; | |
| 748 } | |
| 749 break; | |
| 750 case 4: | |
| 751 if (binary_length <= 56) { | |
| 752 target_bitsize = 56; | |
| 753 } else if (binary_length <= 96) { | |
| 754 target_bitsize = 96; | |
| 755 } else if (binary_length <= 152) { | |
| 756 target_bitsize = 152; | |
| 757 } else if (binary_length <= 208) { | |
| 758 target_bitsize = 208; | |
| 759 } else if (binary_length <= 264) { | |
| 760 target_bitsize = 264; | |
| 761 } else if (binary_length <= 352) { | |
| 762 target_bitsize = 352; | |
| 763 } else if (binary_length <= 496) { | |
| 764 target_bitsize = 496; | |
| 765 } else if (binary_length <= 672) { | |
| 766 target_bitsize = 672; | |
| 767 } else if (binary_length <= 840) { | |
| 768 target_bitsize = 840; | |
| 769 } else if (binary_length <= 1016) { | |
| 770 target_bitsize = 1016; | |
| 771 } else if (binary_length <= 1184) { | |
| 772 target_bitsize = 1184; | |
| 773 } | |
| 774 break; | |
| 775 } | |
| 776 | |
| 777 return target_bitsize; | |
| 778 } | |
| 779 | |
| 780 static int cc_c_calc_padding(const int binary_length, int *p_cc_width, const int linear_width, int *p_ecc_level) { | |
| 781 int target_bitsize = 0; | |
| 782 int byte_length, codewords_used, ecc_level, ecc_codewords, rows; | |
| 783 int codewords_total, target_codewords, target_bytesize; | |
| 784 | |
| 785 byte_length = binary_length / 8; | |
| 786 if (binary_length % 8 != 0) { | |
| 787 byte_length++; | |
| 788 } | |
| 789 | |
| 790 codewords_used = (byte_length / 6) * 5; | |
| 791 codewords_used += byte_length % 6; | |
| 792 | |
| 793 /* Recommended minimum ecc levels ISO/IEC 1543:2015 (PDF417) Annex E Table E.1, | |
| 794 restricted by CC-C codeword max 900 (30 cols * 30 rows), GS1 General Specifications 19.1 5.9.2.3 */ | |
| 795 if (codewords_used <= 40) { | |
| 796 ecc_level = 2; | |
| 797 } else if (codewords_used <= 160) { | |
| 798 ecc_level = 3; | |
| 799 } else if (codewords_used <= 320) { | |
| 800 ecc_level = 4; | |
| 801 } else if (codewords_used <= 833) { /* 900 - 3 - 64 */ | |
| 802 ecc_level = 5; | |
| 803 } else if (codewords_used <= 865) { /* 900 - 3 - 32 */ | |
| 804 ecc_level = 4; /* Not recommended but allow to meet advertised "up to 2361 digits" (allows max 2372) */ | |
| 805 } else { | |
| 806 return 0; | |
| 807 } | |
| 808 *p_ecc_level = ecc_level; | |
| 809 ecc_codewords = 1 << (ecc_level + 1); | |
| 810 | |
| 811 codewords_used += ecc_codewords; | |
| 812 codewords_used += 3; | |
| 813 | |
| 814 /* Minimum possible linear width (with GS1_NO_CHECK) is 11*5 (start, FNC1, linkage, data, check) + 13 stop */ | |
| 815 assert(linear_width >= 68); | |
| 816 /* -52 = 7 left shift (section 12.3 f) + 10 right quiet zone - 17 start + 2x17 row indicators + 18 stop */ | |
| 817 *p_cc_width = linear_width == 68 ? 1 : (linear_width - 52) / 17; /* Ensure > 0 */ | |
| 818 if (*p_cc_width > 30) { | |
| 819 *p_cc_width = 30; | |
| 820 } | |
| 821 assert(*p_cc_width > 0); | |
| 822 rows = (int) ceil((double) codewords_used / *p_cc_width); | |
| 823 /* stop the symbol from becoming too high */ | |
| 824 while (rows > 30 && *p_cc_width < 30) { | |
| 825 (*p_cc_width)++; | |
| 826 rows = (int) ceil((double) codewords_used / *p_cc_width); | |
| 827 } | |
| 828 | |
| 829 if (rows > 30) { /* Should never happen given `codewords_used` check above (865 / 30 ~ 28.83) */ | |
| 830 return 0; /* Not reached */ | |
| 831 } | |
| 832 if (rows < 3) { | |
| 833 rows = 3; | |
| 834 } | |
| 835 | |
| 836 codewords_total = *p_cc_width * rows; | |
| 837 | |
| 838 target_codewords = codewords_total - ecc_codewords; | |
| 839 target_codewords -= 3; | |
| 840 | |
| 841 target_bytesize = 6 * (target_codewords / 5); | |
| 842 target_bytesize += target_codewords % 5; | |
| 843 | |
| 844 target_bitsize = 8 * target_bytesize; | |
| 845 | |
| 846 return target_bitsize; | |
| 847 } | |
| 848 | |
| 849 /* Handles all data encodation from section 5 of ISO/IEC 24723 */ | |
| 850 static int cc_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 851 char binary_string[], const int cc_mode, int *p_cc_width, int *p_ecc_level, const int linear_width) { | |
| 852 int encoding_method, read_posn, alpha_pad; | |
| 853 int i, j, ai_crop, ai_crop_posn, fnc1_latch; | |
| 854 int ai90_mode, remainder; | |
| 855 char last_digit = '\0'; | |
| 856 int mode; | |
| 857 char *general_field = (char *) z_alloca(length + 1); | |
| 858 int target_bitsize; | |
| 859 int bp = 0; | |
| 860 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 861 | |
| 862 encoding_method = 1; | |
| 863 read_posn = 0; | |
| 864 ai_crop = 0; | |
| 865 ai_crop_posn = -1; | |
| 866 fnc1_latch = 0; | |
| 867 alpha_pad = 0; | |
| 868 *p_ecc_level = 0; | |
| 869 target_bitsize = 0; | |
| 870 mode = NUMERIC; | |
| 871 | |
| 872 if (length > 1 && (source[0] == '1') && ((source[1] == '0') || (source[1] == '1') || (source[1] == '7'))) { | |
| 873 /* Source starts (10), (11) or (17) */ | |
| 874 if (source[1] == '0' || dbar_date(source, length, 2) >= 0) { /* Check date valid if (11) or (17) */ | |
| 875 encoding_method = 2; | |
| 876 } | |
| 877 } else if (length > 1 && (source[0] == '9') && (source[1] == '0')) { | |
| 878 /* Source starts (90) */ | |
| 879 encoding_method = 3; | |
| 880 } | |
| 881 | |
| 882 if (encoding_method == 1) { | |
| 883 binary_string[bp++] = '0'; | |
| 884 if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1)); | |
| 885 | |
| 886 } else if (encoding_method == 2) { | |
| 887 /* Encoding Method field "10" - date and lot number */ | |
| 888 | |
| 889 bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */ | |
| 890 | |
| 891 if (source[1] == '0') { | |
| 892 /* No date data */ | |
| 893 bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */ | |
| 894 read_posn = 2; | |
| 895 } else { | |
| 896 /* Production Date (11) or Expiration Date (17) */ | |
| 897 assert(length >= 8); /* Due to `dbar_date()` check above */ | |
| 898 | |
| 899 bp = bin_append_posn(dbar_date(source, length, 2), 16, binary_string, bp); | |
| 900 | |
| 901 if (source[1] == '1') { | |
| 902 /* Production Date AI 11 */ | |
| 903 binary_string[bp++] = '0'; | |
| 904 } else { | |
| 905 /* Expiration Date AI 17 */ | |
| 906 binary_string[bp++] = '1'; | |
| 907 } | |
| 908 read_posn = 8; | |
| 909 | |
| 910 if (read_posn + 1 < length && (source[read_posn] == '1') && (source[read_posn + 1] == '0')) { | |
| 911 /* Followed by AI 10 - strip this from general field */ | |
| 912 read_posn += 2; | |
| 913 } else if (source[read_posn]) { | |
| 914 /* ISO/IEC 24723:2010 5.3.1 "If a lot number does not directly follow the date element string, | |
| 915 a FNC1 is encoded following the date element string ..." */ | |
| 916 fnc1_latch = 1; | |
| 917 } else { | |
| 918 /* "... even if no more data follows the date element string" */ | |
| 919 /* So still need FNC1 character but can't do single FNC1 in numeric mode, so insert alphanumeric latch | |
| 920 "0000" and alphanumeric FNC1 "01111" (this implementation detail taken from BWIPP | |
| 921 https://github.com/bwipp/postscriptbarcode Copyright (c) 2004-2019 Terry Burton) */ | |
| 922 bp = bin_append_posn(15, 9, binary_string, bp); /* "000001111" */ | |
| 923 /* Note an alphanumeric FNC1 is also a numeric latch, so now in numeric mode */ | |
| 924 } | |
| 925 } | |
| 926 | |
| 927 if (debug_print) { | |
| 928 printf("CC-%c Encodation Method: 10, Compaction Field: %.*s\n", 'A' + (cc_mode - 1), read_posn, source); | |
| 929 } | |
| 930 | |
| 931 } else if (encoding_method == 3) { | |
| 932 /* Encodation Method field of "11" - AI 90 */ | |
| 933 unsigned char *ninety = (unsigned char *) z_alloca(length + 1); | |
| 934 int ninety_len, alpha, alphanum, numeric, alpha_posn; | |
| 935 | |
| 936 /* "This encodation method may be used if an element string with an AI | |
| 937 90 occurs at the start of the data message, and if the data field | |
| 938 following the two-digit AI 90 starts with an alphanumeric string which | |
| 939 complies with a specific format." (para 5.3.2) */ | |
| 940 | |
| 941 i = 0; | |
| 942 if (length > 2) { | |
| 943 do { | |
| 944 ninety[i] = source[i + 2]; | |
| 945 i++; | |
| 946 } while (i + 2 < length && source[i + 2] != '\x1D'); | |
| 947 } | |
| 948 ninety[i] = '\0'; | |
| 949 ninety_len = i; | |
| 950 | |
| 951 /* Find out if the AI 90 data is alphabetic or numeric or both */ | |
| 952 | |
| 953 alpha = 0; | |
| 954 alphanum = 0; | |
| 955 numeric = 0; | |
| 956 | |
| 957 for (i = 0; i < ninety_len; i++) { | |
| 958 | |
| 959 if (z_isupper(ninety[i])) { | |
| 960 /* Character is alphabetic */ | |
| 961 alpha += 1; | |
| 962 } else if (z_isdigit(ninety[i])) { | |
| 963 /* Character is numeric */ | |
| 964 numeric += 1; | |
| 965 } else { | |
| 966 alphanum += 1; | |
| 967 } | |
| 968 } | |
| 969 | |
| 970 /* must start with 0, 1, 2 or 3 digits followed by an uppercase character */ | |
| 971 alpha_posn = -1; | |
| 972 if (ninety_len && ninety[0] != '0') { /* Leading zeros are not permitted */ | |
| 973 for (i = 0; i < ninety_len && i < 4; i++) { | |
| 974 if (z_isupper(ninety[i])) { | |
| 975 alpha_posn = i; | |
| 976 break; | |
| 977 } | |
| 978 if (!z_isdigit(ninety[i])) { | |
| 979 break; | |
| 980 } | |
| 981 } | |
| 982 } | |
| 983 | |
| 984 if (alpha_posn != -1) { | |
| 985 int next_ai_posn; | |
| 986 int numeric_value; | |
| 987 int table3_letter; | |
| 988 /* Encodation method "11" can be used */ | |
| 989 bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */ | |
| 990 | |
| 991 numeric -= alpha_posn; | |
| 992 alpha--; | |
| 993 | |
| 994 /* Decide on numeric, alpha or alphanumeric mode */ | |
| 995 /* Alpha mode is a special mode for AI 90 */ | |
| 996 | |
| 997 if (alphanum == 0 && alpha > numeric) { | |
| 998 /* Alpha mode */ | |
| 999 bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */ | |
| 1000 ai90_mode = 2; | |
| 1001 } else if (alphanum == 0 && alpha == 0) { | |
| 1002 /* Numeric mode */ | |
| 1003 bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */ | |
| 1004 ai90_mode = 3; | |
| 1005 } else { | |
| 1006 /* Note if first 4 are digits then it would be shorter to go into NUMERIC mode first; not | |
| 1007 implemented */ | |
| 1008 /* Alphanumeric mode */ | |
| 1009 binary_string[bp++] = '0'; | |
| 1010 ai90_mode = 1; | |
| 1011 mode = ALPHANUMERIC; | |
| 1012 } | |
| 1013 | |
| 1014 next_ai_posn = 2 + ninety_len; | |
| 1015 | |
| 1016 if (next_ai_posn < length && source[next_ai_posn] == '\x1D') { | |
| 1017 /* There are more AIs afterwards */ | |
| 1018 if (next_ai_posn + 2 < length | |
| 1019 && (source[next_ai_posn + 1] == '2') && (source[next_ai_posn + 2] == '1')) { | |
| 1020 /* AI 21 follows */ | |
| 1021 ai_crop = 1; | |
| 1022 } else if (next_ai_posn + 4 < length | |
| 1023 && (source[next_ai_posn + 1] == '8') && (source[next_ai_posn + 2] == '0') | |
| 1024 && (source[next_ai_posn + 3] == '0') && (source[next_ai_posn + 4] == '4')) { | |
| 1025 /* AI 8004 follows */ | |
| 1026 ai_crop = 3; | |
| 1027 } | |
| 1028 } | |
| 1029 | |
| 1030 switch (ai_crop) { | |
| 1031 case 0: binary_string[bp++] = '0'; | |
| 1032 break; | |
| 1033 case 1: bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */ | |
| 1034 ai_crop_posn = next_ai_posn + 1; | |
| 1035 break; | |
| 1036 case 3: bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */ | |
| 1037 ai_crop_posn = next_ai_posn + 1; | |
| 1038 break; | |
| 1039 } | |
| 1040 | |
| 1041 numeric_value = alpha_posn ? to_int(ninety, alpha_posn) : 0; | |
| 1042 | |
| 1043 table3_letter = -1; | |
| 1044 if (numeric_value < 31) { | |
| 1045 table3_letter = posn("BDHIJKLNPQRSTVWZ", ninety[alpha_posn]); | |
| 1046 } | |
| 1047 | |
| 1048 if (table3_letter != -1) { | |
| 1049 /* Encoding can be done according to 5.3.2 c) 2) */ | |
| 1050 /* five bit binary string representing value before letter */ | |
| 1051 bp = bin_append_posn(numeric_value, 5, binary_string, bp); | |
| 1052 | |
| 1053 /* followed by four bit representation of letter from Table 3 */ | |
| 1054 bp = bin_append_posn(table3_letter, 4, binary_string, bp); | |
| 1055 } else { | |
| 1056 /* Encoding is done according to 5.3.2 c) 3) */ | |
| 1057 bp = bin_append_posn(31, 5, binary_string, bp); | |
| 1058 /* ten bit representation of number */ | |
| 1059 bp = bin_append_posn(numeric_value, 10, binary_string, bp); | |
| 1060 | |
| 1061 /* five bit representation of ASCII character */ | |
| 1062 bp = bin_append_posn(ninety[alpha_posn] - 65, 5, binary_string, bp); | |
| 1063 } | |
| 1064 | |
| 1065 read_posn = alpha_posn + 3; /* +2 for 90 and +1 to go beyond alpha position */ | |
| 1066 | |
| 1067 /* Do Alpha mode encoding of the rest of the AI 90 data field here */ | |
| 1068 if (ai90_mode == 2) { | |
| 1069 /* Alpha encodation (section 5.3.3) */ | |
| 1070 do { | |
| 1071 if (z_isupper(source[read_posn])) { | |
| 1072 bp = bin_append_posn(source[read_posn] - 65, 5, binary_string, bp); | |
| 1073 | |
| 1074 } else if (z_isdigit(source[read_posn])) { | |
| 1075 bp = bin_append_posn(source[read_posn] + 4, 6, binary_string, bp); | |
| 1076 | |
| 1077 } else if (source[read_posn] == '\x1D') { | |
| 1078 bp = bin_append_posn(31, 5, binary_string, bp); | |
| 1079 } | |
| 1080 | |
| 1081 read_posn++; | |
| 1082 } while (source[read_posn - 1] != '\x1D' && source[read_posn - 1] != '\0'); | |
| 1083 alpha_pad = 1; /* This is overwritten if a general field is encoded */ | |
| 1084 } | |
| 1085 | |
| 1086 if (debug_print) { | |
| 1087 printf("CC-%c Encodation Method: 11, Compaction Field: %.*s, Binary: %.*s (%d)\n", | |
| 1088 'A' + (cc_mode - 1), read_posn, source, bp, binary_string, bp); | |
| 1089 } | |
| 1090 } else { | |
| 1091 /* Use general field encodation instead */ | |
| 1092 binary_string[bp++] = '0'; | |
| 1093 read_posn = 0; | |
| 1094 if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1)); | |
| 1095 } | |
| 1096 } | |
| 1097 | |
| 1098 /* The compressed data field has been processed if appropriate - the | |
| 1099 rest of the data (if any) goes into a general-purpose data compaction field */ | |
| 1100 | |
| 1101 j = 0; | |
| 1102 if (fnc1_latch == 1) { | |
| 1103 /* Encodation method "10" has been used but it is not followed by | |
| 1104 AI 10, so a FNC1 character needs to be added */ | |
| 1105 general_field[j] = '\x1D'; | |
| 1106 j++; | |
| 1107 } | |
| 1108 | |
| 1109 for (i = read_posn; i < length; i++) { | |
| 1110 /* Skip "[21" or "[8004" AIs if encodation method "11" used */ | |
| 1111 if (i == ai_crop_posn) { | |
| 1112 i += ai_crop; | |
| 1113 } else { | |
| 1114 general_field[j] = source[i]; | |
| 1115 j++; | |
| 1116 } | |
| 1117 } | |
| 1118 general_field[j] = '\0'; | |
| 1119 | |
| 1120 if (debug_print) { | |
| 1121 printf("Mode %s, General Field: %.40s%s\n", | |
| 1122 mode == NUMERIC ? "NUMERIC" : mode == ALPHANUMERIC ? "ALPHANUMERIC" : "ISO646", | |
| 1123 general_field, j > 40 ? "..." : ""); | |
| 1124 } | |
| 1125 | |
| 1126 if (j != 0) { /* If general field not empty */ | |
| 1127 alpha_pad = 0; | |
| 1128 | |
| 1129 if (!general_field_encode(general_field, j, &mode, &last_digit, binary_string, &bp)) { | |
| 1130 /* Invalid character in input data */ | |
| 1131 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 441, "Invalid character in input (2D component)"); | |
| 1132 } | |
| 1133 } | |
| 1134 | |
| 1135 switch (cc_mode) { | |
| 1136 case 1: | |
| 1137 target_bitsize = cc_a_calc_padding(bp, *p_cc_width); | |
| 1138 break; | |
| 1139 case 2: | |
| 1140 target_bitsize = cc_b_calc_padding(bp, *p_cc_width); | |
| 1141 break; | |
| 1142 case 3: | |
| 1143 target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level); | |
| 1144 break; | |
| 1145 } | |
| 1146 | |
| 1147 if (target_bitsize == 0) { | |
| 1148 return errtxt(ZINT_ERROR_TOO_LONG, symbol, 442, "Input too long (2D component)"); | |
| 1149 } | |
| 1150 | |
| 1151 remainder = target_bitsize - bp; | |
| 1152 | |
| 1153 if (last_digit) { | |
| 1154 /* There is still one more numeric digit to encode */ | |
| 1155 | |
| 1156 if ((remainder >= 4) && (remainder <= 6)) { | |
| 1157 /* ISO/IEC 24723:2010 5.4.1 c) 2) "If four to six bits remain, add 1 to the digit value and encode the | |
| 1158 result in the next four bits. ..." */ | |
| 1159 bp = bin_append_posn(ctoi(last_digit) + 1, 4, binary_string, bp); | |
| 1160 if (remainder > 4) { | |
| 1161 /* "... The fifth and sixth bits, if present, shall be “0”s." (Covered by adding truncated | |
| 1162 alphanumeric latch below but do explicitly anyway) */ | |
| 1163 bp = bin_append_posn(0, remainder - 4, binary_string, bp); | |
| 1164 } | |
| 1165 } else { | |
| 1166 bp = bin_append_posn((11 * ctoi(last_digit)) + 18, 7, binary_string, bp); | |
| 1167 /* This may push the symbol up to the next size */ | |
| 1168 } | |
| 1169 } | |
| 1170 | |
| 1171 switch (cc_mode) { | |
| 1172 case 1: | |
| 1173 target_bitsize = cc_a_calc_padding(bp, *p_cc_width); | |
| 1174 break; | |
| 1175 case 2: | |
| 1176 target_bitsize = cc_b_calc_padding(bp, *p_cc_width); | |
| 1177 break; | |
| 1178 case 3: | |
| 1179 target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level); | |
| 1180 break; | |
| 1181 } | |
| 1182 | |
| 1183 if (target_bitsize == 0) { | |
| 1184 return errtxt(ZINT_ERROR_TOO_LONG, symbol, 444, "Input too long (2D component)"); | |
| 1185 } | |
| 1186 | |
| 1187 if (bp < target_bitsize) { | |
| 1188 /* Now add padding to binary string */ | |
| 1189 if (alpha_pad == 1) { | |
| 1190 bp = bin_append_posn(31, 5, binary_string, bp); /* "11111" */ | |
| 1191 /* Extra FNC1 character required after Alpha encodation (section 5.3.3) */ | |
| 1192 } | |
| 1193 | |
| 1194 if (mode == NUMERIC) { | |
| 1195 bp = bin_append_posn(0, 4, binary_string, bp); /* "0000" */ | |
| 1196 } | |
| 1197 | |
| 1198 while (bp < target_bitsize) { | |
| 1199 bp = bin_append_posn(4, 5, binary_string, bp); /* "00100" */ | |
| 1200 } | |
| 1201 } | |
| 1202 binary_string[target_bitsize] = '\0'; | |
| 1203 | |
| 1204 if (debug_print) { | |
| 1205 printf("ECC: %d, CC width %d\n", *p_ecc_level, *p_cc_width); | |
| 1206 printf("Binary: %s (%d)\n", binary_string, target_bitsize); | |
| 1207 } | |
| 1208 | |
| 1209 return 0; | |
| 1210 } | |
| 1211 | |
| 1212 /* Calculate the width of the linear part (primary) */ | |
| 1213 static int cc_linear_dummy_run(int input_mode, unsigned char *source, const int length, const int debug, | |
| 1214 char *errtxt) { | |
| 1215 struct zint_symbol dummy = {0}; | |
| 1216 int error_number; | |
| 1217 int linear_width; | |
| 1218 | |
| 1219 dummy.symbology = BARCODE_GS1_128_CC; | |
| 1220 dummy.option_1 = -1; | |
| 1221 dummy.input_mode = input_mode; | |
| 1222 dummy.debug = debug; | |
| 1223 error_number = gs1_128_cc(&dummy, source, length, 3 /*cc_mode*/, 0 /*cc_rows*/); | |
| 1224 linear_width = dummy.width; | |
| 1225 if (error_number >= ZINT_ERROR || (debug & ZINT_DEBUG_TEST)) { | |
| 1226 strcpy(errtxt, dummy.errtxt); | |
| 1227 } | |
| 1228 | |
| 1229 if (error_number >= ZINT_ERROR) { | |
| 1230 return 0; | |
| 1231 } | |
| 1232 return linear_width; | |
| 1233 } | |
| 1234 | |
| 1235 INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 1236 int error_number, cc_mode, cc_width = 0, ecc_level = 0; | |
| 1237 int j, i, k; | |
| 1238 /* Allow for 8 bits + 5-bit latch per char + 1000 bits overhead/padding */ | |
| 1239 const unsigned int bs = 13 * length + 1000 + 1; | |
| 1240 char *binary_string = (char *) z_alloca(bs); | |
| 1241 unsigned int pri_len; | |
| 1242 struct zint_symbol *linear; | |
| 1243 int top_shift, bottom_shift; | |
| 1244 int linear_width = 0; | |
| 1245 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 1246 | |
| 1247 if (debug_print) printf("Reduced length: %d\n", length); | |
| 1248 | |
| 1249 /* Perform sanity checks on input options first */ | |
| 1250 error_number = 0; | |
| 1251 pri_len = (int) strlen(symbol->primary); | |
| 1252 if (pri_len == 0) { | |
| 1253 /* TODO: change to more appropiate ZINT_ERROR_INVALID_DATA */ | |
| 1254 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 445, "No primary (linear) message"); | |
| 1255 } | |
| 1256 | |
| 1257 if (length > 2990) { | |
| 1258 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 446, | |
| 1259 "2D component input too long, requires %d characters (maximum 2990)", length); | |
| 1260 } | |
| 1261 | |
| 1262 cc_mode = symbol->option_1; | |
| 1263 if ((cc_mode == 3) && (symbol->symbology != BARCODE_GS1_128_CC)) { | |
| 1264 /* CC-C can only be used with a GS1-128 linear part */ | |
| 1265 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 447, | |
| 1266 "Invalid mode (CC-C only valid with GS1-128 linear component)"); | |
| 1267 } | |
| 1268 | |
| 1269 if (symbol->symbology == BARCODE_GS1_128_CC) { | |
| 1270 /* Do a test run of encoding the linear component to establish its width */ | |
| 1271 linear_width = cc_linear_dummy_run(symbol->input_mode, (unsigned char *) symbol->primary, pri_len, | |
| 1272 symbol->debug, symbol->errtxt); | |
| 1273 if (linear_width == 0) { | |
| 1274 return errtxt_adj(ZINT_ERROR_INVALID_DATA, symbol, "%1$s%2$s", " (linear component)"); | |
| 1275 } | |
| 1276 if (debug_print) { | |
| 1277 printf("GS1-128 linear width: %d\n", linear_width); | |
| 1278 } | |
| 1279 } | |
| 1280 | |
| 1281 switch (symbol->symbology) { | |
| 1282 /* Determine width of 2D component according to ISO/IEC 24723 Table 1 */ | |
| 1283 case BARCODE_EANX_CC: | |
| 1284 if (pri_len < 20) { | |
| 1285 int padded_pri_len; | |
| 1286 int with_addon; | |
| 1287 unsigned char padded_pri[21]; | |
| 1288 if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon, NULL, | |
| 1289 NULL)) { | |
| 1290 return errtxt_adj(ZINT_ERROR_TOO_LONG, symbol, "%1$s%2$s", " (linear component)"); | |
| 1291 } | |
| 1292 padded_pri_len = (int) ustrlen(padded_pri); | |
| 1293 if (padded_pri_len <= 7) { /* EAN-8 */ | |
| 1294 cc_width = 3; | |
| 1295 } else { | |
| 1296 switch (padded_pri_len) { | |
| 1297 case 10: /* EAN-8 + 2 */ | |
| 1298 cc_width = 3; | |
| 1299 break; | |
| 1300 case 13: /* EAN-13 CHK or EAN-8 + 5 */ | |
| 1301 cc_width = with_addon ? 3 : 4; | |
| 1302 break; | |
| 1303 case 12: /* EAN-13 */ | |
| 1304 case 15: /* EAN-13 + 2 */ | |
| 1305 case 16: /* EAN-13 CHK + 2 */ | |
| 1306 case 18: /* EAN-13 + 5 */ | |
| 1307 case 19: /* EAN-13 CHK + 5 */ | |
| 1308 cc_width = 4; | |
| 1309 break; | |
| 1310 } | |
| 1311 } | |
| 1312 } | |
| 1313 if (cc_width == 0) { | |
| 1314 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 449, "Input length %d wrong (linear component)", pri_len); | |
| 1315 } | |
| 1316 break; | |
| 1317 case BARCODE_GS1_128_CC: cc_width = 4; | |
| 1318 break; | |
| 1319 case BARCODE_DBAR_OMN_CC: cc_width = 4; | |
| 1320 break; | |
| 1321 case BARCODE_DBAR_LTD_CC: cc_width = 3; | |
| 1322 break; | |
| 1323 case BARCODE_DBAR_EXP_CC: cc_width = 4; | |
| 1324 break; | |
| 1325 case BARCODE_UPCA_CC: cc_width = 4; | |
| 1326 break; | |
| 1327 case BARCODE_UPCE_CC: cc_width = 2; | |
| 1328 break; | |
| 1329 case BARCODE_DBAR_STK_CC: cc_width = 2; | |
| 1330 break; | |
| 1331 case BARCODE_DBAR_OMNSTK_CC: cc_width = 2; | |
| 1332 break; | |
| 1333 case BARCODE_DBAR_EXPSTK_CC: cc_width = 4; | |
| 1334 break; | |
| 1335 } | |
| 1336 | |
| 1337 if (cc_mode < 1 || cc_mode > 3) { | |
| 1338 cc_mode = 1; | |
| 1339 } | |
| 1340 | |
| 1341 if (cc_mode == 1) { | |
| 1342 i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width); | |
| 1343 if (i == ZINT_ERROR_TOO_LONG) { | |
| 1344 symbol->errtxt[0] = '\0'; /* Unset error text */ | |
| 1345 cc_mode = 2; | |
| 1346 } else if (i != 0) { | |
| 1347 return i; | |
| 1348 } | |
| 1349 } | |
| 1350 | |
| 1351 if (cc_mode == 2) { | |
| 1352 /* If the data didn't fit into CC-A it is recalculated for CC-B */ | |
| 1353 i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width); | |
| 1354 if (i == ZINT_ERROR_TOO_LONG) { | |
| 1355 if (symbol->symbology != BARCODE_GS1_128_CC) { | |
| 1356 return ZINT_ERROR_TOO_LONG; | |
| 1357 } | |
| 1358 symbol->errtxt[0] = '\0'; /* Unset error text */ | |
| 1359 cc_mode = 3; | |
| 1360 } else if (i != 0) { | |
| 1361 return i; | |
| 1362 } | |
| 1363 } | |
| 1364 | |
| 1365 if (cc_mode == 3) { | |
| 1366 /* If the data didn't fit in CC-B (and linear part is GS1-128) it is recalculated for CC-C */ | |
| 1367 i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width); | |
| 1368 if (i != 0) { | |
| 1369 return i; | |
| 1370 } | |
| 1371 } | |
| 1372 | |
| 1373 switch (cc_mode) { | |
| 1374 /* Note that ecc_level is only relevant to CC-C */ | |
| 1375 case 1: cc_a(symbol, binary_string, cc_width); | |
| 1376 break; | |
| 1377 case 2: cc_b(symbol, binary_string, cc_width); | |
| 1378 break; | |
| 1379 case 3: cc_c(symbol, binary_string, cc_width, ecc_level); | |
| 1380 break; | |
| 1381 } | |
| 1382 | |
| 1383 /* 2D component done, now calculate linear component */ | |
| 1384 linear = ZBarcode_Create(); /* Symbol contains the 2D component and Linear contains the rest */ | |
| 1385 | |
| 1386 linear->symbology = symbol->symbology; | |
| 1387 linear->input_mode = symbol->input_mode; | |
| 1388 linear->output_options = symbol->output_options; | |
| 1389 linear->show_hrt = symbol->show_hrt; | |
| 1390 linear->option_2 = symbol->option_2; | |
| 1391 linear->option_3 = symbol->option_3; | |
| 1392 /* If symbol->height given minimum row height will be returned, else default height */ | |
| 1393 linear->height = symbol->height; | |
| 1394 linear->debug = symbol->debug; | |
| 1395 | |
| 1396 if (linear->symbology != BARCODE_GS1_128_CC) { | |
| 1397 /* Set the "component linkage" flag in the linear component */ | |
| 1398 linear->option_1 = 2; | |
| 1399 } | |
| 1400 | |
| 1401 switch (symbol->symbology) { | |
| 1402 case BARCODE_EANX_CC: | |
| 1403 error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1404 break; | |
| 1405 case BARCODE_GS1_128_CC: | |
| 1406 /* GS1-128 needs to know which type of 2D component is used */ | |
| 1407 error_number = gs1_128_cc(linear, (unsigned char *) symbol->primary, pri_len, cc_mode, symbol->rows); | |
| 1408 break; | |
| 1409 case BARCODE_DBAR_OMN_CC: | |
| 1410 error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1411 break; | |
| 1412 case BARCODE_DBAR_LTD_CC: | |
| 1413 error_number = dbar_ltd_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1414 break; | |
| 1415 case BARCODE_DBAR_EXP_CC: | |
| 1416 error_number = dbar_exp_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1417 break; | |
| 1418 case BARCODE_UPCA_CC: | |
| 1419 error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1420 break; | |
| 1421 case BARCODE_UPCE_CC: | |
| 1422 error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1423 break; | |
| 1424 case BARCODE_DBAR_STK_CC: | |
| 1425 error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1426 break; | |
| 1427 case BARCODE_DBAR_OMNSTK_CC: | |
| 1428 error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1429 break; | |
| 1430 case BARCODE_DBAR_EXPSTK_CC: | |
| 1431 error_number = dbar_exp_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows); | |
| 1432 break; | |
| 1433 } | |
| 1434 | |
| 1435 if (error_number) { | |
| 1436 errtxtf(0, symbol, -1, "%1$s%2$s", linear->errtxt, " (linear component)"); | |
| 1437 if (error_number >= ZINT_ERROR) { | |
| 1438 ZBarcode_Delete(linear); | |
| 1439 return error_number; | |
| 1440 } | |
| 1441 } | |
| 1442 | |
| 1443 /* Merge the linear component with the 2D component */ | |
| 1444 | |
| 1445 top_shift = 0; | |
| 1446 bottom_shift = 0; | |
| 1447 | |
| 1448 switch (symbol->symbology) { | |
| 1449 /* Determine horizontal alignment (according to section 12.3) */ | |
| 1450 case BARCODE_EANX_CC: | |
| 1451 switch (ustrlen(linear->text)) { /* Use zero-padded length */ | |
| 1452 case 8: /* EAN-8 */ | |
| 1453 case 11: /* EAN-8 + 2 */ | |
| 1454 case 14: /* EAN-8 + 5 */ | |
| 1455 if (cc_mode == 1) { | |
| 1456 bottom_shift = 3; | |
| 1457 } else { | |
| 1458 bottom_shift = 13; | |
| 1459 } | |
| 1460 break; | |
| 1461 case 13: /* EAN-13 */ | |
| 1462 case 16: /* EAN-13 + 2 */ | |
| 1463 case 19: /* EAN-13 + 5 */ | |
| 1464 bottom_shift = 2; | |
| 1465 break; | |
| 1466 } | |
| 1467 break; | |
| 1468 case BARCODE_GS1_128_CC: | |
| 1469 if (cc_mode == 3) { | |
| 1470 bottom_shift = 7; /* ISO/IEC 24723:2010 12.3 f) */ | |
| 1471 } else { | |
| 1472 /* ISO/IEC 24723:2010 12.3 g) "GS1-128 components linked to the right quiet zone of the CC-A or CC-B: | |
| 1473 the CC-A or CC-B component is aligned with the last space module of one of the rightmost symbol | |
| 1474 characters of the linear component. To calculate the target Code 128 symbol character position for | |
| 1475 alignment, number the positions from right to left (0 is the Stop character, 1 is the Check | |
| 1476 character, etc.), and then Position = (total number of Code 128 symbol characters – 9) div 2" | |
| 1477 */ | |
| 1478 const int num_symbols = (linear_width - 2) / 11; | |
| 1479 const int position = (num_symbols - 9) / 2; | |
| 1480 /* Less 1 to align with last space module */ | |
| 1481 int calc_shift = linear->width - position * 11 - 1 - symbol->width; | |
| 1482 if (position) { | |
| 1483 calc_shift -= 2; /* Less additional stop modules */ | |
| 1484 } | |
| 1485 if (calc_shift > 0) { | |
| 1486 top_shift = calc_shift; | |
| 1487 } else if (calc_shift < 0) { | |
| 1488 bottom_shift = -calc_shift; | |
| 1489 } | |
| 1490 } | |
| 1491 break; | |
| 1492 case BARCODE_DBAR_OMN_CC: bottom_shift = 4; | |
| 1493 break; | |
| 1494 case BARCODE_DBAR_LTD_CC: | |
| 1495 if (cc_mode == 1) { | |
| 1496 top_shift = 1; | |
| 1497 } else { | |
| 1498 bottom_shift = 9; | |
| 1499 } | |
| 1500 break; | |
| 1501 case BARCODE_DBAR_EXP_CC: | |
| 1502 for (k = 1; !module_is_set(linear, 1, k - 1) && module_is_set(linear, 1, k); k++); | |
| 1503 top_shift = k; | |
| 1504 break; | |
| 1505 case BARCODE_UPCA_CC: bottom_shift = 2; | |
| 1506 break; | |
| 1507 case BARCODE_UPCE_CC: bottom_shift = 2; | |
| 1508 break; | |
| 1509 case BARCODE_DBAR_STK_CC: top_shift = 1; | |
| 1510 break; | |
| 1511 case BARCODE_DBAR_OMNSTK_CC: top_shift = 1; | |
| 1512 break; | |
| 1513 case BARCODE_DBAR_EXPSTK_CC: | |
| 1514 for (k = 1; !module_is_set(linear, 1, k - 1) && module_is_set(linear, 1, k); k++); | |
| 1515 top_shift = k; | |
| 1516 break; | |
| 1517 } | |
| 1518 | |
| 1519 if (debug_print) { | |
| 1520 printf("Top shift: %d, Bottom shift: %d\n", top_shift, bottom_shift); | |
| 1521 } | |
| 1522 | |
| 1523 if (top_shift != 0) { | |
| 1524 /* Move the 2D component of the symbol horizontally */ | |
| 1525 for (i = 0; i <= symbol->rows; i++) { | |
| 1526 for (j = (symbol->width + top_shift); j >= top_shift; j--) { | |
| 1527 if (module_is_set(symbol, i, j - top_shift)) { | |
| 1528 set_module(symbol, i, j); | |
| 1529 } else { | |
| 1530 unset_module(symbol, i, j); | |
| 1531 } | |
| 1532 } | |
| 1533 for (j = 0; j < top_shift; j++) { | |
| 1534 unset_module(symbol, i, j); | |
| 1535 } | |
| 1536 } | |
| 1537 } | |
| 1538 | |
| 1539 /* Merge linear and 2D components into one structure */ | |
| 1540 for (i = 0; i <= linear->rows; i++) { | |
| 1541 symbol->row_height[symbol->rows + i] = linear->row_height[i]; | |
| 1542 for (j = 0; j <= linear->width; j++) { | |
| 1543 if (module_is_set(linear, i, j)) { | |
| 1544 set_module(symbol, i + symbol->rows, j + bottom_shift); | |
| 1545 } else { | |
| 1546 unset_module(symbol, i + symbol->rows, j + bottom_shift); | |
| 1547 } | |
| 1548 } | |
| 1549 } | |
| 1550 if ((linear->width + bottom_shift) > symbol->width + top_shift) { | |
| 1551 symbol->width = linear->width + bottom_shift; | |
| 1552 } else if ((symbol->width + top_shift) > linear->width + bottom_shift) { | |
| 1553 symbol->width += top_shift; | |
| 1554 } | |
| 1555 symbol->rows += linear->rows; | |
| 1556 if (symbol->output_options & COMPLIANT_HEIGHT) { | |
| 1557 if (symbol->symbology == BARCODE_DBAR_STK_CC) { | |
| 1558 /* Databar Stacked needs special treatment due to asymmetric rows */ | |
| 1559 error_number = dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 /*first_row*/); | |
| 1560 } else if (symbol->symbology == BARCODE_DBAR_EXP_CC || symbol->symbology == BARCODE_DBAR_EXPSTK_CC) { | |
| 1561 /* If symbol->height given then min row height was returned, else default height */ | |
| 1562 if (error_number == 0) { /* Avoid overwriting any `gs1_verify()` warning */ | |
| 1563 error_number = set_height(symbol, symbol->height ? linear->height : 0.0f, | |
| 1564 symbol->height ? 0.0f : linear->height, 0.0f, 0 /*no_errtxt*/); | |
| 1565 } else { | |
| 1566 (void) set_height(symbol, symbol->height ? linear->height : 0.0f, | |
| 1567 symbol->height ? 0.0f : linear->height, 0.0f, 1 /*no_errtxt*/); | |
| 1568 } | |
| 1569 } else { | |
| 1570 /* If symbol->height given then min row height was returned, else default height */ | |
| 1571 error_number = set_height(symbol, symbol->height ? linear->height : 0.0f, | |
| 1572 symbol->height ? 0.0f : linear->height, 0.0f, 0 /*no_errtxt*/); | |
| 1573 } | |
| 1574 } else { | |
| 1575 if (symbol->symbology == BARCODE_DBAR_STK_CC) { | |
| 1576 (void) dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 /*first_row*/); | |
| 1577 } else { | |
| 1578 (void) set_height(symbol, symbol->height ? linear->height : 0.0f, symbol->height ? 0.0f : linear->height, | |
| 1579 0.0f, 1 /*no_errtxt*/); | |
| 1580 } | |
| 1581 } | |
| 1582 | |
| 1583 ustrcpy(symbol->text, linear->text); | |
| 1584 | |
| 1585 ZBarcode_Delete(linear); | |
| 1586 | |
| 1587 return error_number; | |
| 1588 } | |
| 1589 | |
| 1590 /* vim: set ts=4 sw=4 et : */ |
