Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/code49.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 /* code49.c - Handles Code 49 */ | |
| 2 /* | |
| 3 libzint - the open source barcode library | |
| 4 Copyright (C) 2009-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 #include <stdio.h> | |
| 34 #include "common.h" | |
| 35 #include "code49.h" | |
| 36 | |
| 37 static const char C49_INSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*"; | |
| 38 | |
| 39 /* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */ | |
| 40 | |
| 41 INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 42 int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value; | |
| 43 char intermediate[170] = ""; | |
| 44 char *d = intermediate; | |
| 45 int codewords[170], codeword_count; | |
| 46 int c_grid[8][8]; /* Refers to table 3 */ | |
| 47 int w_grid[8][4]; /* Refets to table 2 */ | |
| 48 int pad_count = 0; | |
| 49 char pattern[80]; | |
| 50 int bp = 0; /* Initialize to suppress gcc -Wmaybe-uninitialized warning */ | |
| 51 int gs1; | |
| 52 int h; | |
| 53 int error_number = 0; | |
| 54 | |
| 55 if (length > 81) { | |
| 56 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 430, "Input length %d too long (maximum 81)", length); | |
| 57 } | |
| 58 if ((symbol->input_mode & 0x07) == GS1_MODE) { | |
| 59 gs1 = 1; | |
| 60 *d++ = '*'; /* FNC1 */ | |
| 61 } else { | |
| 62 gs1 = 0; | |
| 63 } | |
| 64 | |
| 65 for (i = 0; i < length; i++) { | |
| 66 if (source[i] > 127) { | |
| 67 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 431, | |
| 68 "Invalid character at position %d in input, extended ASCII not allowed", i + 1); | |
| 69 } | |
| 70 if (gs1 && source[i] == '\x1D') { | |
| 71 *d++ = '*'; /* FNC1 */ | |
| 72 } else { | |
| 73 const char *const entry = c49_table7[source[i]]; | |
| 74 memcpy(d, entry, 2); | |
| 75 d += entry[1] ? 2 : 1; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 codeword_count = 0; | |
| 80 i = 0; | |
| 81 h = d - intermediate; | |
| 82 do { | |
| 83 if (z_isdigit(intermediate[i])) { | |
| 84 /* Numeric data */ | |
| 85 for (j = 0; z_isdigit(intermediate[i + j]); j++); | |
| 86 if (j >= 5) { | |
| 87 /* Use Numeric Encodation Method */ | |
| 88 int block_count, c; | |
| 89 int block_remain; | |
| 90 int block_value; | |
| 91 | |
| 92 codewords[codeword_count] = 48; /* Numeric Shift */ | |
| 93 codeword_count++; | |
| 94 | |
| 95 block_count = j / 5; | |
| 96 block_remain = j % 5; | |
| 97 | |
| 98 for (c = 0; c < block_count; c++) { | |
| 99 if ((c == block_count - 1) && (block_remain == 2)) { | |
| 100 /* Rule (d) */ | |
| 101 block_value = 100000; | |
| 102 block_value += ctoi(intermediate[i]) * 1000; | |
| 103 block_value += ctoi(intermediate[i + 1]) * 100; | |
| 104 block_value += ctoi(intermediate[i + 2]) * 10; | |
| 105 block_value += ctoi(intermediate[i + 3]); | |
| 106 | |
| 107 codewords[codeword_count] = block_value / (48 * 48); | |
| 108 block_value = block_value - (48 * 48) * codewords[codeword_count]; | |
| 109 codeword_count++; | |
| 110 codewords[codeword_count] = block_value / 48; | |
| 111 block_value = block_value - 48 * codewords[codeword_count]; | |
| 112 codeword_count++; | |
| 113 codewords[codeword_count] = block_value; | |
| 114 codeword_count++; | |
| 115 i += 4; | |
| 116 block_value = ctoi(intermediate[i]) * 100; | |
| 117 block_value += ctoi(intermediate[i + 1]) * 10; | |
| 118 block_value += ctoi(intermediate[i + 2]); | |
| 119 | |
| 120 codewords[codeword_count] = block_value / 48; | |
| 121 block_value = block_value - 48 * codewords[codeword_count]; | |
| 122 codeword_count++; | |
| 123 codewords[codeword_count] = block_value; | |
| 124 codeword_count++; | |
| 125 i += 3; | |
| 126 } else { | |
| 127 block_value = ctoi(intermediate[i]) * 10000; | |
| 128 block_value += ctoi(intermediate[i + 1]) * 1000; | |
| 129 block_value += ctoi(intermediate[i + 2]) * 100; | |
| 130 block_value += ctoi(intermediate[i + 3]) * 10; | |
| 131 block_value += ctoi(intermediate[i + 4]); | |
| 132 | |
| 133 codewords[codeword_count] = block_value / (48 * 48); | |
| 134 block_value = block_value - (48 * 48) * codewords[codeword_count]; | |
| 135 codeword_count++; | |
| 136 codewords[codeword_count] = block_value / 48; | |
| 137 block_value = block_value - 48 * codewords[codeword_count]; | |
| 138 codeword_count++; | |
| 139 codewords[codeword_count] = block_value; | |
| 140 codeword_count++; | |
| 141 i += 5; | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 switch (block_remain) { | |
| 146 case 1: | |
| 147 /* Rule (a) */ | |
| 148 codewords[codeword_count] = posn(C49_INSET, intermediate[i]); | |
| 149 codeword_count++; | |
| 150 i++; | |
| 151 break; | |
| 152 case 3: | |
| 153 /* Rule (b) */ | |
| 154 block_value = ctoi(intermediate[i]) * 100; | |
| 155 block_value += ctoi(intermediate[i + 1]) * 10; | |
| 156 block_value += ctoi(intermediate[i + 2]); | |
| 157 | |
| 158 codewords[codeword_count] = block_value / 48; | |
| 159 block_value = block_value - 48 * codewords[codeword_count]; | |
| 160 codeword_count++; | |
| 161 codewords[codeword_count] = block_value; | |
| 162 codeword_count++; | |
| 163 i += 3; | |
| 164 break; | |
| 165 case 4: | |
| 166 /* Rule (c) */ | |
| 167 block_value = 100000; | |
| 168 block_value += ctoi(intermediate[i]) * 1000; | |
| 169 block_value += ctoi(intermediate[i + 1]) * 100; | |
| 170 block_value += ctoi(intermediate[i + 2]) * 10; | |
| 171 block_value += ctoi(intermediate[i + 3]); | |
| 172 | |
| 173 codewords[codeword_count] = block_value / (48 * 48); | |
| 174 block_value = block_value - (48 * 48) * codewords[codeword_count]; | |
| 175 codeword_count++; | |
| 176 codewords[codeword_count] = block_value / 48; | |
| 177 block_value = block_value - 48 * codewords[codeword_count]; | |
| 178 codeword_count++; | |
| 179 codewords[codeword_count] = block_value; | |
| 180 codeword_count++; | |
| 181 i += 4; | |
| 182 break; | |
| 183 } | |
| 184 if (i < h) { | |
| 185 /* There is more to add */ | |
| 186 codewords[codeword_count] = 48; /* Numeric Shift */ | |
| 187 codeword_count++; | |
| 188 } | |
| 189 } else { | |
| 190 codewords[codeword_count] = posn(C49_INSET, intermediate[i]); | |
| 191 codeword_count++; | |
| 192 i++; | |
| 193 } | |
| 194 } else { | |
| 195 codewords[codeword_count] = posn(C49_INSET, intermediate[i]); | |
| 196 codeword_count++; | |
| 197 i++; | |
| 198 } | |
| 199 } while (i < h); | |
| 200 | |
| 201 switch (codewords[0]) { | |
| 202 /* Set starting mode value */ | |
| 203 case 48: M = 2; | |
| 204 break; | |
| 205 case 43: M = 4; | |
| 206 break; | |
| 207 case 44: M = 5; | |
| 208 break; | |
| 209 default: M = 0; | |
| 210 break; | |
| 211 } | |
| 212 | |
| 213 if (M != 0) { | |
| 214 codeword_count--; | |
| 215 for (i = 0; i < codeword_count; i++) { | |
| 216 codewords[i] = codewords[i + 1]; | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 if (codeword_count > 49) { | |
| 221 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 432, "Input too long, requires %d codewords (maximum 49)", | |
| 222 codeword_count); | |
| 223 } | |
| 224 | |
| 225 /* Place codewords in code character array (c grid) */ | |
| 226 rows = 0; | |
| 227 do { | |
| 228 for (i = 0; i < 7; i++) { | |
| 229 if (((rows * 7) + i) < codeword_count) { | |
| 230 c_grid[rows][i] = codewords[(rows * 7) + i]; | |
| 231 } else { | |
| 232 c_grid[rows][i] = 48; /* Pad */ | |
| 233 pad_count++; | |
| 234 } | |
| 235 } | |
| 236 rows++; | |
| 237 } while ((rows * 7) < codeword_count); | |
| 238 | |
| 239 if ((((rows <= 6) && (pad_count < 5))) || (rows > 6) || (rows == 1)) { | |
| 240 /* Add a row */ | |
| 241 for (i = 0; i < 7; i++) { | |
| 242 c_grid[rows][i] = 48; /* Pad */ | |
| 243 } | |
| 244 rows++; | |
| 245 } | |
| 246 | |
| 247 if (symbol->option_1 >= 2 && symbol->option_1 <= 8) { /* Minimum no. of rows */ | |
| 248 if (symbol->option_1 > rows) { | |
| 249 for (j = symbol->option_1 - rows; j > 0; j--) { | |
| 250 for (i = 0; i < 7; i++) { | |
| 251 c_grid[rows][i] = 48; /* Pad */ | |
| 252 } | |
| 253 rows++; | |
| 254 } | |
| 255 } | |
| 256 } else if (symbol->option_1 >= 1) { | |
| 257 strcpy(symbol->errtxt, "433: Minimum number of rows out of range (2 to 8)"); | |
| 258 return ZINT_ERROR_INVALID_OPTION; | |
| 259 } | |
| 260 | |
| 261 /* Add row count and mode character */ | |
| 262 c_grid[rows - 1][6] = (7 * (rows - 2)) + M; | |
| 263 | |
| 264 /* Add row check character */ | |
| 265 for (i = 0; i < rows - 1; i++) { | |
| 266 int row_sum = 0; | |
| 267 | |
| 268 for (j = 0; j < 7; j++) { | |
| 269 row_sum += c_grid[i][j]; | |
| 270 } | |
| 271 c_grid[i][7] = row_sum % 49; | |
| 272 } | |
| 273 | |
| 274 /* Calculate Symbol Check Characters */ | |
| 275 posn_val = 0; | |
| 276 x_count = c_grid[rows - 1][6] * 20; | |
| 277 y_count = c_grid[rows - 1][6] * 16; | |
| 278 z_count = c_grid[rows - 1][6] * 38; | |
| 279 for (i = 0; i < rows - 1; i++) { | |
| 280 for (j = 0; j < 4; j++) { | |
| 281 local_value = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1]; | |
| 282 x_count += c49_x_weight[posn_val] * local_value; | |
| 283 y_count += c49_y_weight[posn_val] * local_value; | |
| 284 z_count += c49_z_weight[posn_val] * local_value; | |
| 285 posn_val++; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 if (rows > 6) { | |
| 290 /* Add Z Symbol Check */ | |
| 291 c_grid[rows - 1][0] = (z_count % 2401) / 49; | |
| 292 c_grid[rows - 1][1] = (z_count % 2401) % 49; | |
| 293 } | |
| 294 | |
| 295 local_value = (c_grid[rows - 1][0] * 49) + c_grid[rows - 1][1]; | |
| 296 x_count += c49_x_weight[posn_val] * local_value; | |
| 297 y_count += c49_y_weight[posn_val] * local_value; | |
| 298 posn_val++; | |
| 299 | |
| 300 /* Add Y Symbol Check */ | |
| 301 c_grid[rows - 1][2] = (y_count % 2401) / 49; | |
| 302 c_grid[rows - 1][3] = (y_count % 2401) % 49; | |
| 303 | |
| 304 local_value = (c_grid[rows - 1][2] * 49) + c_grid[rows - 1][3]; | |
| 305 x_count += c49_x_weight[posn_val] * local_value; | |
| 306 | |
| 307 /* Add X Symbol Check */ | |
| 308 c_grid[rows - 1][4] = (x_count % 2401) / 49; | |
| 309 c_grid[rows - 1][5] = (x_count % 2401) % 49; | |
| 310 | |
| 311 /* Add last row check character */ | |
| 312 j = 0; | |
| 313 for (i = 0; i < 7; i++) { | |
| 314 j += c_grid[rows - 1][i]; | |
| 315 } | |
| 316 c_grid[rows - 1][7] = j % 49; | |
| 317 | |
| 318 if (symbol->debug & ZINT_DEBUG_PRINT) { | |
| 319 fputs("Codewords:\n", stdout); | |
| 320 for (i = 0; i < rows; i++) { | |
| 321 for (j = 0; j < 8; j++) { | |
| 322 printf(" %2d", c_grid[i][j]); | |
| 323 } | |
| 324 fputc('\n', stdout); | |
| 325 } | |
| 326 } | |
| 327 #ifdef ZINT_TEST | |
| 328 if (symbol->debug & ZINT_DEBUG_TEST) { | |
| 329 debug_test_codeword_dump_int(symbol, (int *)c_grid, rows * 8); | |
| 330 } | |
| 331 #endif | |
| 332 | |
| 333 /* Transfer data to symbol character array (w grid) */ | |
| 334 for (i = 0; i < rows; i++) { | |
| 335 for (j = 0; j < 4; j++) { | |
| 336 w_grid[i][j] = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1]; | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 for (i = 0; i < rows; i++) { | |
| 341 bp = 0; | |
| 342 bp = bin_append_posn(2, 2, pattern, bp); /* Start character "10" */ | |
| 343 for (j = 0; j < 4; j++) { | |
| 344 if (i != (rows - 1)) { | |
| 345 if (c49_table4[i][j] == 'E') { | |
| 346 /* Even Parity */ | |
| 347 bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp); | |
| 348 } else { | |
| 349 /* Odd Parity */ | |
| 350 bp = bin_append_posn(c49_odd_bitpattern[w_grid[i][j]], 16, pattern, bp); | |
| 351 } | |
| 352 } else { | |
| 353 /* Last row uses all even parity */ | |
| 354 bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp); | |
| 355 } | |
| 356 } | |
| 357 bp = bin_append_posn(15, 4, pattern, bp); /* Stop character "1111" */ | |
| 358 | |
| 359 /* Expand into symbol */ | |
| 360 for (j = 0; j < bp; j++) { | |
| 361 if (pattern[j] == '1') { | |
| 362 set_module(symbol, i, j); | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 symbol->rows = rows; | |
| 368 symbol->width = bp; | |
| 369 | |
| 370 if (symbol->output_options & COMPLIANT_HEIGHT) { | |
| 371 /* ANSI/AIM BC6-2000 Section 2.6 minimum 8X; use 10X as default | |
| 372 Formula 2 H = ((h + g)r + g)X = rows * row_height + (rows - 1) * separator as borders not included | |
| 373 in symbol->height (added on) */ | |
| 374 const int separator = symbol->option_3 >= 1 && symbol->option_3 <= 4 ? symbol->option_3 : 1; | |
| 375 const float min_row_height = stripf((8.0f * rows + separator * (rows - 1)) / rows); | |
| 376 const float default_height = 10.0f * rows + separator * (rows - 1); | |
| 377 error_number = set_height(symbol, min_row_height, default_height, 0.0f, 0 /*no_errtxt*/); | |
| 378 } else { | |
| 379 (void) set_height(symbol, 0.0f, 10.0f * rows, 0.0f, 1 /*no_errtxt*/); | |
| 380 } | |
| 381 | |
| 382 symbol->output_options |= BARCODE_BIND; | |
| 383 | |
| 384 if (symbol->border_width == 0) { /* Allow override if non-zero */ | |
| 385 symbol->border_width = 1; /* ANSI/AIM BC6-2000 Section 2.1 (note change from previous default 2) */ | |
| 386 } | |
| 387 | |
| 388 return error_number; | |
| 389 } | |
| 390 | |
| 391 /* vim: set ts=4 sw=4 et : */ |
