Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/plessey.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 /* plessey.c - Handles Plessey and MSI Plessey */ | |
| 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 #include <stdio.h> | |
| 34 #include "common.h" | |
| 35 | |
| 36 #define SSET_F (IS_NUM_F | IS_UHX_F) /* SSET "0123456789ABCDEF" */ | |
| 37 | |
| 38 static const char PlessTable[16][8] = { | |
| 39 {'1','3','1','3','1','3','1','3'}, {'3','1','1','3','1','3','1','3'}, {'1','3','3','1','1','3','1','3'}, | |
| 40 {'3','1','3','1','1','3','1','3'}, {'1','3','1','3','3','1','1','3'}, {'3','1','1','3','3','1','1','3'}, | |
| 41 {'1','3','3','1','3','1','1','3'}, {'3','1','3','1','3','1','1','3'}, {'1','3','1','3','1','3','3','1'}, | |
| 42 {'3','1','1','3','1','3','3','1'}, {'1','3','3','1','1','3','3','1'}, {'3','1','3','1','1','3','3','1'}, | |
| 43 {'1','3','1','3','3','1','3','1'}, {'3','1','1','3','3','1','3','1'}, {'1','3','3','1','3','1','3','1'}, | |
| 44 {'3','1','3','1','3','1','3','1'} | |
| 45 }; | |
| 46 | |
| 47 static const char MSITable[10][8] = { | |
| 48 {'1','2','1','2','1','2','1','2'}, {'1','2','1','2','1','2','2','1'}, {'1','2','1','2','2','1','1','2'}, | |
| 49 {'1','2','1','2','2','1','2','1'}, {'1','2','2','1','1','2','1','2'}, {'1','2','2','1','1','2','2','1'}, | |
| 50 {'1','2','2','1','2','1','1','2'}, {'1','2','2','1','2','1','2','1'}, {'2','1','1','2','1','2','1','2'}, | |
| 51 {'2','1','1','2','1','2','2','1'} | |
| 52 }; | |
| 53 | |
| 54 /* Not MSI/Plessey but the older Plessey standard */ | |
| 55 INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 56 | |
| 57 int i; | |
| 58 unsigned char checkptr[67 * 4 + 8] = {0}; | |
| 59 static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1}; | |
| 60 char dest[570]; /* 8 + 67 * 8 + 2 * 8 + 9 + 1 = 570 */ | |
| 61 char *d = dest; | |
| 62 int error_number = 0; | |
| 63 | |
| 64 if (length > 67) { /* 16 + 67 * 16 + 4 * 8 + 19 = 1139 */ | |
| 65 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 370, "Input length %d too long (maximum 67)", length); | |
| 66 } | |
| 67 if ((i = not_sane(SSET_F, source, length))) { | |
| 68 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 371, | |
| 69 "Invalid character at position %d in input (digits and \"ABCDEF\" only)", i); | |
| 70 } | |
| 71 | |
| 72 /* Start character */ | |
| 73 memcpy(d, "31311331", 8); | |
| 74 d += 8; | |
| 75 | |
| 76 /* Data area */ | |
| 77 for (i = 0; i < length; i++, d += 8) { | |
| 78 unsigned int check = source[i] - '0' - (source[i] >> 6) * 7; | |
| 79 memcpy(d, PlessTable[check], 8); | |
| 80 checkptr[4 * i] = check & 1; | |
| 81 checkptr[4 * i + 1] = (check >> 1) & 1; | |
| 82 checkptr[4 * i + 2] = (check >> 2) & 1; | |
| 83 checkptr[4 * i + 3] = (check >> 3) & 1; | |
| 84 } | |
| 85 | |
| 86 /* CRC check digit code adapted from code by Leonid A. Broukhis | |
| 87 used in GNU Barcode */ | |
| 88 | |
| 89 for (i = 0; i < (4 * length); i++) { | |
| 90 if (checkptr[i]) { | |
| 91 int j; | |
| 92 for (j = 0; j < 9; j++) | |
| 93 checkptr[i + j] ^= grid[j]; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 for (i = 0; i < 8; i++) { | |
| 98 switch (checkptr[length * 4 + i]) { | |
| 99 case 0: memcpy(d, "13", 2); | |
| 100 d += 2; | |
| 101 break; | |
| 102 case 1: memcpy(d, "31", 2); | |
| 103 d += 2; | |
| 104 break; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 /* Stop character */ | |
| 109 memcpy(d, "331311313", 9); | |
| 110 d += 9; | |
| 111 | |
| 112 expand(symbol, dest, d - dest); | |
| 113 | |
| 114 /* TODO: Find documentation on BARCODE_PLESSEY dimensions/height */ | |
| 115 | |
| 116 symbol->text[0] = '\0'; | |
| 117 ustrncat(symbol->text, source, length); | |
| 118 | |
| 119 return error_number; | |
| 120 } | |
| 121 | |
| 122 /* Modulo 10 check digit - Luhn algorithm | |
| 123 See https://en.wikipedia.org/wiki/Luhn_algorithm */ | |
| 124 static char msi_check_digit_mod10(const unsigned char source[], const int length) { | |
| 125 static const char vals[2][10] = { | |
| 126 { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }, /* Doubled and digits summed */ | |
| 127 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* Single */ | |
| 128 }; | |
| 129 int i, x = 0, undoubled = 0; | |
| 130 | |
| 131 for (i = length - 1; i >= 0; i--) { | |
| 132 /* Note overflow impossible for max length 92 * max weight 9 * max val 15 == 12420 */ | |
| 133 x += vals[undoubled][ctoi(source[i])]; | |
| 134 undoubled = !undoubled; | |
| 135 } | |
| 136 | |
| 137 return itoc((10 - x % 10) % 10); | |
| 138 } | |
| 139 | |
| 140 /* Modulo 11 check digit - IBM weight system wrap = 7, NCR system wrap = 9 | |
| 141 See https://en.wikipedia.org/wiki/MSI_Barcode */ | |
| 142 static char msi_check_digit_mod11(const unsigned char source[], const int length, const int wrap) { | |
| 143 int i, x = 0, weight = 2; | |
| 144 | |
| 145 for (i = length - 1; i >= 0; i--) { | |
| 146 /* Note overflow impossible for max length 92 * max weight 9 * max val 15 == 12420 */ | |
| 147 x += weight * ctoi(source[i]); | |
| 148 weight++; | |
| 149 if (weight > wrap) { | |
| 150 weight = 2; | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 return itoc((11 - x % 11) % 11); /* Will return ':' for 10 */ | |
| 155 } | |
| 156 | |
| 157 /* Plain MSI Plessey - does not calculate any check character */ | |
| 158 static char *msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 159 char *d) { | |
| 160 | |
| 161 int i; | |
| 162 | |
| 163 for (i = 0; i < length; i++, d += 8) { | |
| 164 memcpy(d, MSITable[source[i] - '0'], 8); | |
| 165 } | |
| 166 | |
| 167 symbol->text[0] = '\0'; | |
| 168 ustrncat(symbol->text, source, length); | |
| 169 | |
| 170 return d; | |
| 171 } | |
| 172 | |
| 173 /* MSI Plessey with Modulo 10 check digit */ | |
| 174 static char *msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 175 const int no_checktext, char *d) { | |
| 176 int i; | |
| 177 char check_digit; | |
| 178 | |
| 179 /* draw data section */ | |
| 180 for (i = 0; i < length; i++, d += 8) { | |
| 181 memcpy(d, MSITable[source[i] - '0'], 8); | |
| 182 } | |
| 183 | |
| 184 /* calculate check digit */ | |
| 185 check_digit = msi_check_digit_mod10(source, length); | |
| 186 | |
| 187 /* draw check digit */ | |
| 188 memcpy(d, MSITable[check_digit - '0'], 8); | |
| 189 d += 8; | |
| 190 | |
| 191 symbol->text[0] = '\0'; | |
| 192 ustrncat(symbol->text, source, length); | |
| 193 if (!no_checktext) { | |
| 194 symbol->text[length] = check_digit; | |
| 195 symbol->text[length + 1] = '\0'; | |
| 196 } | |
| 197 | |
| 198 return d; | |
| 199 } | |
| 200 | |
| 201 /* MSI Plessey with two Modulo 10 check digits */ | |
| 202 static char *msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 203 const int no_checktext, char *d) { | |
| 204 | |
| 205 int i; | |
| 206 unsigned char temp[92 + 2 + 1]; | |
| 207 | |
| 208 /* Append check digits */ | |
| 209 temp[0] = '\0'; | |
| 210 ustrncat(temp, source, length); | |
| 211 temp[length] = msi_check_digit_mod10(source, length); | |
| 212 temp[length + 1] = msi_check_digit_mod10(temp, length + 1); | |
| 213 temp[length + 2] = '\0'; | |
| 214 | |
| 215 /* draw data section */ | |
| 216 for (i = 0; i < length + 2; i++, d += 8) { | |
| 217 memcpy(d, MSITable[temp[i] - '0'], 8); | |
| 218 } | |
| 219 | |
| 220 if (no_checktext) { | |
| 221 symbol->text[0] = '\0'; | |
| 222 ustrncat(symbol->text, source, length); | |
| 223 } else { | |
| 224 ustrcpy(symbol->text, temp); | |
| 225 } | |
| 226 | |
| 227 return d; | |
| 228 } | |
| 229 | |
| 230 /* MSI Plessey with Modulo 11 check digit */ | |
| 231 static char *msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 232 const int no_checktext, const int wrap, char *d) { | |
| 233 /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ | |
| 234 int i; | |
| 235 char check_digit; | |
| 236 | |
| 237 /* draw data section */ | |
| 238 for (i = 0; i < length; i++, d += 8) { | |
| 239 memcpy(d, MSITable[source[i] - '0'], 8); | |
| 240 } | |
| 241 | |
| 242 /* Append check digit */ | |
| 243 check_digit = msi_check_digit_mod11(source, length, wrap); | |
| 244 if (check_digit == ':') { | |
| 245 memcpy(d, MSITable[1], 8); | |
| 246 d += 8; | |
| 247 memcpy(d, MSITable[0], 8); | |
| 248 d += 8; | |
| 249 } else { | |
| 250 memcpy(d, MSITable[check_digit - '0'], 8); | |
| 251 d += 8; | |
| 252 } | |
| 253 | |
| 254 symbol->text[0] = '\0'; | |
| 255 ustrncat(symbol->text, source, length); | |
| 256 if (!no_checktext) { | |
| 257 if (check_digit == ':') { | |
| 258 ustrcat(symbol->text, "10"); | |
| 259 } else { | |
| 260 symbol->text[length] = check_digit; | |
| 261 symbol->text[length + 1] = '\0'; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 return d; | |
| 266 } | |
| 267 | |
| 268 /* MSI Plessey with Modulo 11 check digit and Modulo 10 check digit */ | |
| 269 static char *msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char source[], const int length, | |
| 270 const int no_checktext, const int wrap, char *d) { | |
| 271 /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ | |
| 272 int i; | |
| 273 char check_digit; | |
| 274 unsigned char temp[92 + 3 + 1]; | |
| 275 int temp_len = length; | |
| 276 | |
| 277 temp[0] = '\0'; | |
| 278 ustrncat(temp, source, length); | |
| 279 | |
| 280 /* Append first (mod 11) digit */ | |
| 281 check_digit = msi_check_digit_mod11(source, length, wrap); | |
| 282 if (check_digit == ':') { | |
| 283 temp[temp_len++] = '1'; | |
| 284 temp[temp_len++] = '0'; | |
| 285 } else { | |
| 286 temp[temp_len++] = check_digit; | |
| 287 } | |
| 288 | |
| 289 /* Append second (mod 10) check digit */ | |
| 290 temp[temp_len] = msi_check_digit_mod10(temp, temp_len); | |
| 291 temp[++temp_len] = '\0'; | |
| 292 | |
| 293 /* draw data section */ | |
| 294 for (i = 0; i < temp_len; i++, d += 8) { | |
| 295 memcpy(d, MSITable[temp[i] - '0'], 8); | |
| 296 } | |
| 297 | |
| 298 if (no_checktext) { | |
| 299 symbol->text[0] = '\0'; | |
| 300 ustrncat(symbol->text, source, length); | |
| 301 } else { | |
| 302 ustrcpy(symbol->text, temp); | |
| 303 } | |
| 304 | |
| 305 return d; | |
| 306 } | |
| 307 | |
| 308 INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) { | |
| 309 int error_number = 0; | |
| 310 int i; | |
| 311 char dest[766]; /* 2 + 92 * 8 + 3 * 8 + 3 + 1 = 766 */ | |
| 312 char *d = dest; | |
| 313 int check_option = symbol->option_2; | |
| 314 int no_checktext = 0; | |
| 315 | |
| 316 if (length > 92) { /* 3 (Start) + 92 * 12 + 3 * 12 + 4 (Stop) = 1147 */ | |
| 317 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 372, "Input length %d too long (maximum 92)", length); | |
| 318 } | |
| 319 if ((i = not_sane(NEON_F, source, length))) { | |
| 320 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 377, | |
| 321 "Invalid character at position %d in input (digits only)", i); | |
| 322 } | |
| 323 | |
| 324 if (check_option >= 11 && check_option <= 16) { /* +10 means don't print check digits in HRT */ | |
| 325 check_option -= 10; | |
| 326 no_checktext = 1; | |
| 327 } | |
| 328 if ((check_option < 0) || (check_option > 6)) { | |
| 329 check_option = 0; | |
| 330 } | |
| 331 | |
| 332 /* Start character */ | |
| 333 memcpy(d, "21", 2); | |
| 334 d += 2; | |
| 335 | |
| 336 switch (check_option) { | |
| 337 case 0: d = msi_plessey_nomod(symbol, source, length, d); | |
| 338 break; | |
| 339 case 1: d = msi_plessey_mod10(symbol, source, length, no_checktext, d); | |
| 340 break; | |
| 341 case 2: d = msi_plessey_mod1010(symbol, source, length, no_checktext, d); | |
| 342 break; | |
| 343 case 3: d = msi_plessey_mod11(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d); | |
| 344 break; | |
| 345 case 4: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d); | |
| 346 break; | |
| 347 case 5: d = msi_plessey_mod11(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d); | |
| 348 break; | |
| 349 case 6: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d); | |
| 350 break; | |
| 351 } | |
| 352 | |
| 353 /* Stop character */ | |
| 354 memcpy(d, "121", 3); | |
| 355 d += 3; | |
| 356 | |
| 357 expand(symbol, dest, d - dest); | |
| 358 | |
| 359 /* TODO: Find documentation on BARCODE_MSI_PLESSEY dimensions/height */ | |
| 360 | |
| 361 return error_number; | |
| 362 } | |
| 363 | |
| 364 /* vim: set ts=4 sw=4 et : */ |
