Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/library.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 /* library.c - external functions of libzint */ | |
| 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 <assert.h> | |
| 34 #include <errno.h> | |
| 35 #include <limits.h> | |
| 36 #include <math.h> | |
| 37 #include <stdio.h> | |
| 38 #include "common.h" | |
| 39 #include "eci.h" | |
| 40 #include "gs1.h" | |
| 41 #include "output.h" | |
| 42 #include "zfiletypes.h" | |
| 43 | |
| 44 /* It's assumed that int is at least 32 bits, the following will compile-time fail if not | |
| 45 * https://stackoverflow.com/a/1980056 */ | |
| 46 typedef char static_assert_int_at_least_32bits[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; | |
| 47 | |
| 48 typedef char static_assert_uint16_is_16bits[sizeof(uint16_t) * CHAR_BIT != 16 ? -1 : 1]; | |
| 49 typedef char static_assert_int32_is_32bits[sizeof(int32_t) * CHAR_BIT != 32 ? -1 : 1]; | |
| 50 typedef char static_assert_uint32_is_32bits[sizeof(uint32_t) * CHAR_BIT != 32 ? -1 : 1]; | |
| 51 typedef char static_assert_uint64_at_least_64bits[sizeof(uint64_t) * CHAR_BIT < 64 ? -1 : 1]; | |
| 52 | |
| 53 /* Set `symbol` to defaults (does not zeroize) */ | |
| 54 static void set_symbol_defaults(struct zint_symbol *symbol) { | |
| 55 | |
| 56 symbol->symbology = BARCODE_CODE128; | |
| 57 symbol->scale = 1.0f; | |
| 58 strcpy(symbol->fgcolour, "000000"); | |
| 59 symbol->fgcolor = &symbol->fgcolour[0]; | |
| 60 strcpy(symbol->bgcolour, "ffffff"); | |
| 61 symbol->bgcolor = &symbol->bgcolour[0]; | |
| 62 #ifdef ZINT_NO_PNG | |
| 63 strcpy(symbol->outfile, "out.gif"); | |
| 64 #else | |
| 65 strcpy(symbol->outfile, "out.png"); | |
| 66 #endif | |
| 67 symbol->option_1 = -1; | |
| 68 symbol->show_hrt = 1; /* Show human readable text */ | |
| 69 symbol->input_mode = DATA_MODE; | |
| 70 symbol->eci = 0; /* Default 0 uses ECI 3 */ | |
| 71 symbol->dot_size = 0.8f; /* 0.4 / 0.5 */ | |
| 72 symbol->text_gap = 1.0f; | |
| 73 symbol->guard_descent = 5.0f; | |
| 74 symbol->warn_level = WARN_DEFAULT; | |
| 75 symbol->bitmap = NULL; | |
| 76 symbol->alphamap = NULL; | |
| 77 symbol->vector = NULL; | |
| 78 symbol->memfile = NULL; | |
| 79 } | |
| 80 | |
| 81 /* Create and initialize a symbol structure */ | |
| 82 struct zint_symbol *ZBarcode_Create(void) { | |
| 83 struct zint_symbol *symbol; | |
| 84 | |
| 85 symbol = (struct zint_symbol *) calloc(1, sizeof(*symbol)); | |
| 86 if (!symbol) return NULL; | |
| 87 | |
| 88 set_symbol_defaults(symbol); | |
| 89 | |
| 90 return symbol; | |
| 91 } | |
| 92 | |
| 93 INTERNAL void vector_free(struct zint_symbol *symbol); /* Free vector structures */ | |
| 94 | |
| 95 /* Free any output buffers that may have been created and initialize output fields */ | |
| 96 void ZBarcode_Clear(struct zint_symbol *symbol) { | |
| 97 int i; | |
| 98 | |
| 99 if (!symbol) return; | |
| 100 | |
| 101 for (i = 0; i < symbol->rows; i++) { | |
| 102 memset(symbol->encoded_data[i], 0, sizeof(symbol->encoded_data[0])); | |
| 103 } | |
| 104 symbol->rows = 0; | |
| 105 symbol->width = 0; | |
| 106 memset(symbol->row_height, 0, sizeof(symbol->row_height)); | |
| 107 memset(symbol->text, 0, sizeof(symbol->text)); | |
| 108 symbol->errtxt[0] = '\0'; | |
| 109 if (symbol->bitmap != NULL) { | |
| 110 free(symbol->bitmap); | |
| 111 symbol->bitmap = NULL; | |
| 112 } | |
| 113 if (symbol->alphamap != NULL) { | |
| 114 free(symbol->alphamap); | |
| 115 symbol->alphamap = NULL; | |
| 116 } | |
| 117 symbol->bitmap_width = 0; | |
| 118 symbol->bitmap_height = 0; | |
| 119 if (symbol->memfile != NULL) { | |
| 120 free(symbol->memfile); | |
| 121 symbol->memfile = NULL; | |
| 122 } | |
| 123 symbol->memfile_size = 0; | |
| 124 | |
| 125 /* If there is a rendered version, ensure its memory is released */ | |
| 126 vector_free(symbol); | |
| 127 } | |
| 128 | |
| 129 /* Free any output buffers that may have been created and reset all fields to defaults */ | |
| 130 void ZBarcode_Reset(struct zint_symbol *symbol) { | |
| 131 if (!symbol) return; | |
| 132 | |
| 133 if (symbol->bitmap != NULL) | |
| 134 free(symbol->bitmap); | |
| 135 if (symbol->alphamap != NULL) | |
| 136 free(symbol->alphamap); | |
| 137 if (symbol->memfile != NULL) | |
| 138 free(symbol->memfile); | |
| 139 | |
| 140 vector_free(symbol); | |
| 141 | |
| 142 memset(symbol, 0, sizeof(*symbol)); | |
| 143 set_symbol_defaults(symbol); | |
| 144 } | |
| 145 | |
| 146 /* Free a symbol structure, including any output buffers */ | |
| 147 void ZBarcode_Delete(struct zint_symbol *symbol) { | |
| 148 if (!symbol) return; | |
| 149 | |
| 150 if (symbol->bitmap != NULL) | |
| 151 free(symbol->bitmap); | |
| 152 if (symbol->alphamap != NULL) | |
| 153 free(symbol->alphamap); | |
| 154 if (symbol->memfile != NULL) | |
| 155 free(symbol->memfile); | |
| 156 | |
| 157 vector_free(symbol); | |
| 158 | |
| 159 free(symbol); | |
| 160 } | |
| 161 | |
| 162 /* Symbology handlers */ | |
| 163 INTERNAL int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */ | |
| 164 INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 3 from 9 (or Code 39) */ | |
| 165 INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */ | |
| 166 /* Extended Code 3 from 9 (or Code 39+) */ | |
| 167 INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 168 /* Codabar - a simple substitution cipher */ | |
| 169 INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 170 /* Code 2 of 5 Standard (& Matrix) */ | |
| 171 INTERNAL int c25standard(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 172 INTERNAL int c25ind(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Industrial */ | |
| 173 INTERNAL int c25iata(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 IATA */ | |
| 174 INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Interleaved */ | |
| 175 INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Data Logic */ | |
| 176 INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length); /* ITF-14 */ | |
| 177 INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */ | |
| 178 INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */ | |
| 179 /* Code 93 - a re-working of Code 39+, generates 2 check digits */ | |
| 180 INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 181 INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 128 and NVE-18 */ | |
| 182 INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-128 (GS1-128) */ | |
| 183 INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */ | |
| 184 INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */ | |
| 185 INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen ASCII */ | |
| 186 INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen Numeric */ | |
| 187 INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* Plessey Code */ | |
| 188 INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode One Track */ | |
| 189 INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length); /* Flattermarken */ | |
| 190 INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length); /* Facing Identification Mark */ | |
| 191 INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode Two Track */ | |
| 192 INTERNAL int postnet(struct zint_symbol *symbol, unsigned char source[], int length); /* Postnet */ | |
| 193 INTERNAL int planet(struct zint_symbol *symbol, unsigned char source[], int length); /* PLANET */ | |
| 194 /* Intelligent Mail (aka USPS OneCode) */ | |
| 195 INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 196 INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */ | |
| 197 INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */ | |
| 198 INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */ | |
| 199 INTERNAL int pdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* PDF417 */ | |
| 200 INTERNAL int micropdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Micro PDF417 */ | |
| 201 INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Maxicode */ | |
| 202 INTERNAL int dbar_omn(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Omnidirectional */ | |
| 203 INTERNAL int dbar_ltd(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Limited */ | |
| 204 INTERNAL int dbar_exp(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Expanded */ | |
| 205 INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */ | |
| 206 INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length); /* TNT KIX Code */ | |
| 207 INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Aztec Code */ | |
| 208 INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length); /* Italian Pharmacode */ | |
| 209 INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length); /* DAFT Code */ | |
| 210 INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-14 */ | |
| 211 INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length); /* NVE-18 */ | |
| 212 INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length); /* Micro QR Code */ | |
| 213 INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */ | |
| 214 INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */ | |
| 215 INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */ | |
| 216 INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 49 */ | |
| 217 INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */ | |
| 218 INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Code One */ | |
| 219 INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Grid Matrix */ | |
| 220 INTERNAL int hanxin(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Han Xin */ | |
| 221 INTERNAL int dotcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* DotCode */ | |
| 222 INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int length); /* Codablock */ | |
| 223 INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length); /* UPNQR */ | |
| 224 INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* QR Code */ | |
| 225 /* Data Matrix (IEC16022) */ | |
| 226 INTERNAL int datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); | |
| 227 /* VIN Code (Vehicle Identification Number) */ | |
| 228 INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 229 /* Royal Mail 2D Mailmark */ | |
| 230 INTERNAL int mailmark_2d(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 231 /* Royal Mail 4-state Mailmark */ | |
| 232 INTERNAL int mailmark_4s(struct zint_symbol *symbol, unsigned char source[], int length); | |
| 233 INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int length); /* Universal Postal Union S10 */ | |
| 234 INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Ultracode */ | |
| 235 INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* rMQR */ | |
| 236 INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length); /* DPD Code */ | |
| 237 INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int length); /* BC412 */ | |
| 238 INTERNAL int dxfilmedge(struct zint_symbol *symbol, unsigned char source[], int length); /* DX Film Edge Barcode */ | |
| 239 | |
| 240 /* Output handlers */ | |
| 241 /* Plot to BMP/GIF/PCX/PNG/TIF */ | |
| 242 INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); | |
| 243 /* Plot to EMF/EPS/SVG */ | |
| 244 INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); | |
| 245 | |
| 246 /* Prefix error message with Error/Warning */ | |
| 247 static int error_tag(int error_number, struct zint_symbol *symbol, const int err_id, const char *error_string) { | |
| 248 | |
| 249 if (error_number != 0) { | |
| 250 if (error_string) { | |
| 251 errtxt(0, symbol, err_id, error_string); | |
| 252 } | |
| 253 if (error_number < ZINT_ERROR && symbol->warn_level == WARN_FAIL_ALL) { | |
| 254 /* Convert to error equivalent */ | |
| 255 if (error_number == ZINT_WARN_NONCOMPLIANT) { | |
| 256 error_number = ZINT_ERROR_NONCOMPLIANT; | |
| 257 } else if (error_number == ZINT_WARN_USES_ECI) { | |
| 258 error_number = ZINT_ERROR_USES_ECI; | |
| 259 } else if (error_number == ZINT_WARN_INVALID_OPTION) { | |
| 260 error_number = ZINT_ERROR_INVALID_OPTION; | |
| 261 } else if (error_number == ZINT_WARN_HRT_TRUNCATED) { | |
| 262 error_number = ZINT_ERROR_HRT_TRUNCATED; | |
| 263 } else { /* Shouldn't happen */ | |
| 264 assert(0); /* Not reached */ | |
| 265 error_number = ZINT_ERROR_ENCODING_PROBLEM; | |
| 266 } | |
| 267 } | |
| 268 if (error_number >= ZINT_ERROR) { | |
| 269 errtxt_adj(0, symbol, "Error %s", NULL); | |
| 270 } else { | |
| 271 errtxt_adj(0, symbol, "Warning %s", NULL); | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 return error_number; | |
| 276 } | |
| 277 | |
| 278 #ifdef ZINT_TEST /* Wrapper for direct testing */ | |
| 279 INTERNAL int error_tag_test(int error_number, struct zint_symbol *symbol, const int err_id, | |
| 280 const char *error_string) { | |
| 281 return error_tag(error_number, symbol, err_id, error_string); | |
| 282 } | |
| 283 #endif | |
| 284 | |
| 285 /* Output a hexadecimal representation of the rendered symbol */ | |
| 286 static int dump_plot(struct zint_symbol *symbol) { | |
| 287 FILE *f; | |
| 288 int i, r; | |
| 289 static const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |
| 290 int space = 0; | |
| 291 const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; | |
| 292 | |
| 293 if (output_to_stdout) { | |
| 294 f = stdout; | |
| 295 } else { | |
| 296 #ifdef _WIN32 | |
| 297 f = out_win_fopen(symbol->outfile, "w"); | |
| 298 #else | |
| 299 f = fopen(symbol->outfile, "w"); | |
| 300 #endif | |
| 301 if (!f) { | |
| 302 return errtxt(ZINT_ERROR_FILE_ACCESS, symbol, 201, "Could not open output file"); | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 for (r = 0; r < symbol->rows; r++) { | |
| 307 int byt = 0; | |
| 308 for (i = 0; i < symbol->width; i++) { | |
| 309 byt = byt << 1; | |
| 310 if (symbol->symbology == BARCODE_ULTRA) { | |
| 311 if (module_colour_is_set(symbol, r, i)) { | |
| 312 byt += 1; | |
| 313 } | |
| 314 } else { | |
| 315 if (module_is_set(symbol, r, i)) { | |
| 316 byt += 1; | |
| 317 } | |
| 318 } | |
| 319 if (((i + 1) % 4) == 0) { | |
| 320 fputc(hex[byt], f); | |
| 321 space++; | |
| 322 byt = 0; | |
| 323 } | |
| 324 if (space == 2 && i + 1 < symbol->width) { | |
| 325 fputc(' ', f); | |
| 326 space = 0; | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 if ((symbol->width % 4) != 0) { | |
| 331 byt = byt << (4 - (symbol->width % 4)); | |
| 332 fputc(hex[byt], f); | |
| 333 } | |
| 334 fputc('\n', f); | |
| 335 space = 0; | |
| 336 } | |
| 337 | |
| 338 if (ferror(f)) { | |
| 339 errtxtf(0, symbol, 795, "Incomplete write to output (%1$d: %2$s)", errno, strerror(errno)); | |
| 340 if (!output_to_stdout) { | |
| 341 (void) fclose(f); | |
| 342 } | |
| 343 return ZINT_ERROR_FILE_WRITE; | |
| 344 } | |
| 345 | |
| 346 if (output_to_stdout) { | |
| 347 if (fflush(f) != 0) { | |
| 348 return errtxtf(ZINT_ERROR_FILE_WRITE, symbol, 796, "Incomplete flush to output (%1$d: %2$s)", | |
| 349 errno, strerror(errno)); | |
| 350 } | |
| 351 } else { | |
| 352 if (fclose(f) != 0) { | |
| 353 return errtxtf(ZINT_ERROR_FILE_WRITE, symbol, 792, "Failure on closing output file (%1$d: %2$s)", | |
| 354 errno, strerror(errno)); | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 return 0; | |
| 359 } | |
| 360 | |
| 361 /* Permitted HIBC characters */ | |
| 362 static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */ | |
| 363 | |
| 364 /* Process health industry bar code data */ | |
| 365 static int hibc(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 366 unsigned char *source = segs[0].source; | |
| 367 int length = segs[0].length; | |
| 368 | |
| 369 int i; | |
| 370 int counter, error_number = 0; | |
| 371 char to_process[110 + 2 + 1]; | |
| 372 int posns[110]; | |
| 373 | |
| 374 /* without "+" and check: max 110 characters in HIBC 2.6 */ | |
| 375 if (length > 110) { | |
| 376 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 202, "Input length %d too long for HIBC LIC (maximum 110)", | |
| 377 length); | |
| 378 } | |
| 379 to_upper(source, length); | |
| 380 if ((i = not_sane_lookup(TECHNETIUM, sizeof(TECHNETIUM) - 1, source, length, posns))) { | |
| 381 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 203, | |
| 382 "Invalid character at position %d in input (alphanumerics, space and \"-.$/+%%\" only)", i); | |
| 383 } | |
| 384 | |
| 385 counter = 41; | |
| 386 for (i = 0; i < length; i++) { | |
| 387 counter += posns[i]; | |
| 388 } | |
| 389 counter = counter % 43; | |
| 390 | |
| 391 to_process[0] = '+'; | |
| 392 memcpy(to_process + 1, source, length); | |
| 393 to_process[++length] = TECHNETIUM[counter]; | |
| 394 to_process[++length] = '\0'; | |
| 395 | |
| 396 segs[0].source = (unsigned char *) to_process; | |
| 397 segs[0].length = length; | |
| 398 | |
| 399 if (symbol->debug & ZINT_DEBUG_PRINT) printf("HIBC processed source: %s\n", to_process); | |
| 400 | |
| 401 switch (symbol->symbology) { | |
| 402 case BARCODE_HIBC_128: | |
| 403 error_number = code128(symbol, segs[0].source, segs[0].length); | |
| 404 ustrcpy(symbol->text, "*"); | |
| 405 ustrcat(symbol->text, to_process); | |
| 406 ustrcat(symbol->text, "*"); | |
| 407 break; | |
| 408 case BARCODE_HIBC_39: | |
| 409 symbol->option_2 = 0; | |
| 410 error_number = code39(symbol, segs[0].source, segs[0].length); | |
| 411 ustrcpy(symbol->text, "*"); | |
| 412 ustrcat(symbol->text, to_process); | |
| 413 ustrcat(symbol->text, "*"); | |
| 414 break; | |
| 415 case BARCODE_HIBC_DM: | |
| 416 error_number = datamatrix(symbol, segs, seg_count); | |
| 417 break; | |
| 418 case BARCODE_HIBC_QR: | |
| 419 error_number = qrcode(symbol, segs, seg_count); | |
| 420 break; | |
| 421 case BARCODE_HIBC_PDF: | |
| 422 error_number = pdf417(symbol, segs, seg_count); | |
| 423 break; | |
| 424 case BARCODE_HIBC_MICPDF: | |
| 425 error_number = micropdf417(symbol, segs, seg_count); | |
| 426 break; | |
| 427 case BARCODE_HIBC_AZTEC: | |
| 428 error_number = aztec(symbol, segs, seg_count); | |
| 429 break; | |
| 430 case BARCODE_HIBC_BLOCKF: | |
| 431 error_number = codablockf(symbol, segs[0].source, segs[0].length); | |
| 432 break; | |
| 433 } | |
| 434 | |
| 435 return error_number; | |
| 436 } | |
| 437 | |
| 438 /* Returns 1 if symbology MUST have GS1 data */ | |
| 439 static int check_force_gs1(const int symbology) { | |
| 440 | |
| 441 switch (symbology) { | |
| 442 case BARCODE_GS1_128: | |
| 443 case BARCODE_EAN14: | |
| 444 case BARCODE_NVE18: | |
| 445 case BARCODE_DBAR_EXP: | |
| 446 case BARCODE_DBAR_EXPSTK: | |
| 447 return 1; | |
| 448 break; | |
| 449 } | |
| 450 | |
| 451 return is_composite(symbology); | |
| 452 } | |
| 453 | |
| 454 /* Returns 1 if symbology supports GS1 data */ | |
| 455 static int gs1_compliant(const int symbology) { | |
| 456 | |
| 457 switch (symbology) { | |
| 458 case BARCODE_CODE16K: | |
| 459 case BARCODE_AZTEC: | |
| 460 case BARCODE_DATAMATRIX: | |
| 461 case BARCODE_CODE49: | |
| 462 case BARCODE_QRCODE: | |
| 463 case BARCODE_DOTCODE: | |
| 464 case BARCODE_CODEONE: | |
| 465 case BARCODE_ULTRA: | |
| 466 case BARCODE_RMQR: | |
| 467 /* TODO: case BARCODE_CODABLOCKF: */ | |
| 468 /* TODO: case BARCODE_HANXIN: */ | |
| 469 /* TODO: case BARCODE_GRIDMATRIX: */ | |
| 470 return 1; | |
| 471 break; | |
| 472 } | |
| 473 | |
| 474 return check_force_gs1(symbology); | |
| 475 } | |
| 476 | |
| 477 /* Returns 1 if symbology can encode the ECI character */ | |
| 478 static int supports_eci(const int symbology) { | |
| 479 | |
| 480 switch (symbology) { | |
| 481 case BARCODE_AZTEC: | |
| 482 case BARCODE_DATAMATRIX: | |
| 483 case BARCODE_MAXICODE: | |
| 484 case BARCODE_MICROPDF417: | |
| 485 case BARCODE_PDF417: | |
| 486 case BARCODE_PDF417COMP: | |
| 487 case BARCODE_QRCODE: | |
| 488 case BARCODE_DOTCODE: | |
| 489 case BARCODE_CODEONE: | |
| 490 case BARCODE_GRIDMATRIX: | |
| 491 case BARCODE_HANXIN: | |
| 492 case BARCODE_ULTRA: | |
| 493 case BARCODE_RMQR: | |
| 494 return 1; | |
| 495 break; | |
| 496 } | |
| 497 | |
| 498 return 0; | |
| 499 } | |
| 500 | |
| 501 /* Returns 1 if symbology supports HRT */ | |
| 502 static int has_hrt(const int symbology) { | |
| 503 | |
| 504 if (is_fixed_ratio(symbology)) { | |
| 505 return 0; | |
| 506 } | |
| 507 | |
| 508 switch (symbology) { /* These don't support HRT */ | |
| 509 case BARCODE_CODE16K: | |
| 510 case BARCODE_CODE49: | |
| 511 case BARCODE_FLAT: | |
| 512 case BARCODE_POSTNET: | |
| 513 case BARCODE_FIM: | |
| 514 case BARCODE_PHARMA: | |
| 515 case BARCODE_PHARMA_TWO: | |
| 516 case BARCODE_DXFILMEDGE: | |
| 517 case BARCODE_CEPNET: | |
| 518 case BARCODE_PDF417: | |
| 519 case BARCODE_PDF417COMP: | |
| 520 case BARCODE_AUSPOST: | |
| 521 case BARCODE_AUSREPLY: | |
| 522 case BARCODE_AUSROUTE: | |
| 523 case BARCODE_AUSREDIRECT: | |
| 524 case BARCODE_RM4SCC: | |
| 525 case BARCODE_CODABLOCKF: | |
| 526 case BARCODE_JAPANPOST: | |
| 527 case BARCODE_DBAR_STK: | |
| 528 case BARCODE_DBAR_OMNSTK: | |
| 529 case BARCODE_DBAR_EXPSTK: | |
| 530 case BARCODE_PLANET: | |
| 531 case BARCODE_MICROPDF417: | |
| 532 case BARCODE_USPS_IMAIL: | |
| 533 case BARCODE_KIX: | |
| 534 case BARCODE_DAFT: | |
| 535 case BARCODE_HIBC_PDF: | |
| 536 case BARCODE_HIBC_MICPDF: | |
| 537 case BARCODE_HIBC_BLOCKF: | |
| 538 case BARCODE_MAILMARK_2D: | |
| 539 case BARCODE_MAILMARK_4S: | |
| 540 case BARCODE_DBAR_STK_CC: | |
| 541 case BARCODE_DBAR_OMNSTK_CC: | |
| 542 case BARCODE_DBAR_EXPSTK_CC: | |
| 543 return 0; | |
| 544 break; | |
| 545 } | |
| 546 | |
| 547 return 1; | |
| 548 } | |
| 549 | |
| 550 typedef int (*barcode_src_func_t)(struct zint_symbol *, unsigned char[], int); | |
| 551 typedef int (*barcode_seg_func_t)(struct zint_symbol *, struct zint_seg[], const int); | |
| 552 | |
| 553 /* Used for dispatching `barcode_src_func_t` barcodes */ | |
| 554 /* Also used, with `barcode_seg_funcs` below, for testing whether symbol id valid in `ZBarcode_ValidID()` */ | |
| 555 static const barcode_src_func_t barcode_src_funcs[BARCODE_LAST + 1] = { | |
| 556 NULL, code11, c25standard, c25inter, c25iata, /*0-4*/ | |
| 557 NULL, c25logic, c25ind, code39, excode39, /*5-9*/ | |
| 558 NULL, NULL, NULL, eanx, eanx, /*10-14*/ | |
| 559 NULL, gs1_128, NULL, codabar, NULL, /*15-19*/ | |
| 560 code128, dpleit, dpident, code16k, code49, /*20-24*/ | |
| 561 code93, NULL, NULL, flat, dbar_omn, /*25-29*/ | |
| 562 dbar_ltd, dbar_exp, telepen, NULL, eanx, /*30-34*/ | |
| 563 eanx, NULL, eanx, eanx, NULL, /*35-39*/ | |
| 564 postnet, NULL, NULL, NULL, NULL, /*40-44*/ | |
| 565 NULL, NULL, msi_plessey, NULL, fim, /*45-49*/ | |
| 566 code39, pharma, pzn, pharma_two, postnet, /*50-54*/ | |
| 567 NULL, NULL, NULL, NULL, NULL, /*55-59*/ | |
| 568 code128, NULL, NULL, auspost, NULL, /*60-64*/ | |
| 569 NULL, auspost, auspost, auspost, eanx, /*65-69*/ | |
| 570 rm4scc, NULL, ean14, vin, codablockf, /*70-74*/ | |
| 571 nve18, japanpost, koreapost, NULL, dbar_omn, /*75-79*/ | |
| 572 dbar_omn, dbar_exp, planet, NULL, NULL, /*80-84*/ | |
| 573 usps_imail, plessey, telepen_num, NULL, itf14, /*85-89*/ | |
| 574 kix, NULL, NULL, daft, NULL, /*90-94*/ | |
| 575 NULL, dpd, microqr, NULL, NULL, /*95-99*/ | |
| 576 NULL, NULL, NULL, NULL, NULL, /*100-104*/ | |
| 577 NULL, NULL, NULL, NULL, NULL, /*105-109*/ | |
| 578 NULL, NULL, NULL, NULL, NULL, /*110-114*/ | |
| 579 NULL, NULL, NULL, NULL, mailmark_2d, /*115-119*/ | |
| 580 upu_s10, mailmark_4s, NULL, NULL, NULL, /*120-124*/ | |
| 581 NULL, NULL, NULL, azrune, code32, /*125-129*/ | |
| 582 composite, composite, composite, composite, composite, /*130-134*/ | |
| 583 composite, composite, composite, composite, composite, /*135-139*/ | |
| 584 channel, NULL, NULL, upnqr, NULL, /*140-144*/ | |
| 585 NULL, bc412, dxfilmedge, /*145-147*/ | |
| 586 }; | |
| 587 | |
| 588 #define LIB_SEG_FUNCS_START 55 | |
| 589 | |
| 590 /* Used for dispatching `barcode_seg_func_t` barcodes */ | |
| 591 static const barcode_seg_func_t barcode_seg_funcs[BARCODE_LAST + 1 - LIB_SEG_FUNCS_START] = { | |
| 592 pdf417, pdf417, maxicode, qrcode, NULL, /*55-59*/ | |
| 593 NULL, NULL, NULL, NULL, NULL, /*60-64*/ | |
| 594 NULL, NULL, NULL, NULL, NULL, /*65-69*/ | |
| 595 NULL, datamatrix, NULL, NULL, NULL, /*70-74*/ | |
| 596 NULL, NULL, NULL, NULL, NULL, /*75-79*/ | |
| 597 NULL, NULL, NULL, NULL, micropdf417, /*80-84*/ | |
| 598 NULL, NULL, NULL, NULL, NULL, /*85-89*/ | |
| 599 NULL, NULL, aztec, NULL, NULL, /*90-94*/ | |
| 600 NULL, NULL, NULL, hibc, hibc, /*95-99*/ | |
| 601 NULL, NULL, hibc, NULL, hibc, /*100-104*/ | |
| 602 NULL, hibc, NULL, hibc, NULL, /*105-109*/ | |
| 603 hibc, NULL, hibc, NULL, NULL, /*110-114*/ | |
| 604 dotcode, hanxin, NULL, NULL, NULL, /*115-119*/ | |
| 605 NULL, NULL, NULL, NULL, NULL, /*120-124*/ | |
| 606 NULL, NULL, NULL, NULL, NULL, /*125-129*/ | |
| 607 NULL, NULL, NULL, NULL, NULL, /*130-134*/ | |
| 608 NULL, NULL, NULL, NULL, NULL, /*135-139*/ | |
| 609 NULL, codeone, gridmatrix, NULL, ultra, /*140-144*/ | |
| 610 rmqr, NULL, /*145-146*/ | |
| 611 }; | |
| 612 | |
| 613 static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); | |
| 614 | |
| 615 /* Main dispatch, checking for barcodes which handle ECIs/character sets themselves, otherwise calling | |
| 616 `reduced_charset()` */ | |
| 617 static int extended_or_reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 618 int error_number = 0; | |
| 619 | |
| 620 switch (symbol->symbology) { | |
| 621 /* These are the "elite" standards which have support for specific character sets + ECI */ | |
| 622 case BARCODE_QRCODE: | |
| 623 case BARCODE_GRIDMATRIX: | |
| 624 case BARCODE_HANXIN: | |
| 625 case BARCODE_RMQR: | |
| 626 error_number = barcode_seg_funcs[symbol->symbology - LIB_SEG_FUNCS_START](symbol, segs, seg_count); | |
| 627 break; | |
| 628 /* These are the standards which have support for specific character sets but not ECI */ | |
| 629 case BARCODE_MICROQR: | |
| 630 case BARCODE_UPNQR: | |
| 631 error_number = barcode_src_funcs[symbol->symbology](symbol, segs[0].source, segs[0].length); | |
| 632 break; | |
| 633 default: error_number = reduced_charset(symbol, segs, seg_count); | |
| 634 break; | |
| 635 } | |
| 636 | |
| 637 return error_number; | |
| 638 } | |
| 639 | |
| 640 /* These are the "norm" standards which only support Latin-1 at most, though a few support ECI */ | |
| 641 static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 642 int error_number = 0; | |
| 643 int i; | |
| 644 struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count); | |
| 645 int *convertible = (int *) z_alloca(sizeof(int) * seg_count); | |
| 646 | |
| 647 if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible_segs(segs, seg_count, convertible)) { | |
| 648 unsigned char *preprocessed; | |
| 649 const int eci_length_segs = get_eci_length_segs(segs, seg_count); | |
| 650 unsigned char *preprocessed_buf = (unsigned char *) z_alloca(eci_length_segs + seg_count); | |
| 651 | |
| 652 /* Prior check ensures ECI only set for those that support it */ | |
| 653 segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */ | |
| 654 preprocessed = preprocessed_buf; | |
| 655 for (i = 0; i < seg_count; i++) { | |
| 656 if (convertible[i]) { | |
| 657 error_number = utf8_to_eci(local_segs[i].eci, local_segs[i].source, preprocessed, | |
| 658 &local_segs[i].length); | |
| 659 if (error_number != 0) { | |
| 660 if (local_segs[i].eci) { | |
| 661 return errtxtf(error_number, symbol, 244, "Invalid character in input for ECI '%d'", | |
| 662 local_segs[i].eci); | |
| 663 } | |
| 664 return errtxt(error_number, symbol, 204, "Invalid character in input (ISO/IEC 8859-1 only)"); | |
| 665 } | |
| 666 local_segs[i].source = preprocessed; | |
| 667 preprocessed += local_segs[i].length + 1; | |
| 668 } | |
| 669 } | |
| 670 if (barcode_src_funcs[symbol->symbology]) { | |
| 671 error_number = barcode_src_funcs[symbol->symbology](symbol, local_segs[0].source, local_segs[0].length); | |
| 672 } else { | |
| 673 assert(symbol->symbology >= LIB_SEG_FUNCS_START); /* Suppress clang-tidy-20 warning */ | |
| 674 assert(barcode_seg_funcs[symbol->symbology - LIB_SEG_FUNCS_START]); /* Suppress clang-tidy-20 warning */ | |
| 675 error_number = barcode_seg_funcs[symbol->symbology - LIB_SEG_FUNCS_START](symbol, local_segs, seg_count); | |
| 676 } | |
| 677 } else { | |
| 678 if (barcode_src_funcs[symbol->symbology]) { | |
| 679 error_number = barcode_src_funcs[symbol->symbology](symbol, segs[0].source, segs[0].length); | |
| 680 } else { | |
| 681 assert(symbol->symbology >= LIB_SEG_FUNCS_START); /* Suppress clang-tidy-19 warning */ | |
| 682 assert(barcode_seg_funcs[symbol->symbology - LIB_SEG_FUNCS_START]); /* Suppress clang-tidy-19 warning */ | |
| 683 segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */ | |
| 684 error_number = barcode_seg_funcs[symbol->symbology - LIB_SEG_FUNCS_START](symbol, local_segs, seg_count); | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 return error_number; | |
| 689 } | |
| 690 | |
| 691 /* Remove Unicode BOM at start of data */ | |
| 692 static void strip_bom(unsigned char *source, int *input_length) { | |
| 693 int i; | |
| 694 | |
| 695 /* Note if BOM is only data then not stripped */ | |
| 696 if (*input_length > 3 && (source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) { | |
| 697 /* BOM at start of input data, strip in accordance with RFC 3629 */ | |
| 698 for (i = 3; i <= *input_length; i++) { /* Include terminating NUL */ | |
| 699 source[i - 3] = source[i]; | |
| 700 } | |
| 701 *input_length -= 3; | |
| 702 } | |
| 703 } | |
| 704 | |
| 705 #ifdef ZINT_TEST /* Wrapper for direct testing */ | |
| 706 INTERNAL void strip_bom_test(unsigned char *source, int *input_length) { | |
| 707 strip_bom(source, input_length); | |
| 708 } | |
| 709 #endif | |
| 710 | |
| 711 /* Helper to convert base octal, decimal, hexadecimal escape sequence */ | |
| 712 static int esc_base(struct zint_symbol *symbol, const unsigned char *input_string, const int length, | |
| 713 const int in_posn, const unsigned char base) { | |
| 714 int c1, c2, c3; | |
| 715 int min_len = base == 'x' ? 2 : 3; | |
| 716 int val = -1; | |
| 717 | |
| 718 if (in_posn + min_len > length) { | |
| 719 return errtxtf(-1, symbol, 232, "Incomplete '\\%c' escape sequence in input", base); | |
| 720 } | |
| 721 c1 = ctoi(input_string[in_posn]); | |
| 722 c2 = ctoi(input_string[in_posn + 1]); | |
| 723 if (base == 'd') { | |
| 724 c3 = ctoi(input_string[in_posn + 2]); | |
| 725 if ((c1 >= 0 && c1 <= 9) && (c2 >= 0 && c2 <= 9) && (c3 >= 0 && c3 <= 9)) { | |
| 726 val = c1 * 100 + c2 * 10 + c3; | |
| 727 } | |
| 728 } else if (base == 'o') { | |
| 729 c3 = ctoi(input_string[in_posn + 2]); | |
| 730 if ((c1 >= 0 && c1 <= 7) && (c2 >= 0 && c2 <= 7) && (c3 >= 0 && c3 <= 7)) { | |
| 731 val = (c1 << 6) | (c2 << 3) | c3; | |
| 732 } | |
| 733 } else { | |
| 734 if ((c1 >= 0) && (c2 >= 0)) { | |
| 735 val = (c1 << 4) | c2; | |
| 736 } | |
| 737 } | |
| 738 | |
| 739 if (val == -1) { | |
| 740 return errtxtf(-1, symbol, 238, "Invalid character in escape sequence '%2$.*1$s' in input (%3$s only)", | |
| 741 base == 'x' ? 4 : 5, input_string + in_posn - 2, | |
| 742 base == 'd' ? "decimal" : base == 'o' ? "octal" : "hexadecimal"); | |
| 743 } | |
| 744 if (val > 255) { | |
| 745 assert(base != 'x'); | |
| 746 return errtxtf(-1, symbol, 237, "Value of escape sequence '%1$.5s' in input out of range (000 to %2$s)", | |
| 747 input_string + in_posn - 2, base == 'd' ? "255" : "377"); | |
| 748 } | |
| 749 | |
| 750 return val; | |
| 751 } | |
| 752 | |
| 753 /* Helper to parse escape sequences. If `escaped_string` NULL, calculates length only */ | |
| 754 static int escape_char_process(struct zint_symbol *symbol, const unsigned char *input_string, int *p_length, | |
| 755 unsigned char *escaped_string) { | |
| 756 /* NUL EOT BEL BS HT LF VT FF CR ESC GS RS \ */ | |
| 757 static const char escs[] = { '0', 'E', 'a', 'b', 't', 'n', 'v', 'f', 'r', 'e', 'G', 'R', '\\', '\0' }; | |
| 758 static const char vals[] = { 0x00, 0x04, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x1B, 0x1D, 0x1E, 0x5C }; | |
| 759 const int length = *p_length; | |
| 760 int in_posn = 0, out_posn = 0; | |
| 761 unsigned char ch; | |
| 762 int val; | |
| 763 int i; | |
| 764 unsigned int unicode; | |
| 765 const int extra_escape_mode = (symbol->input_mode & EXTRA_ESCAPE_MODE) && symbol->symbology == BARCODE_CODE128; | |
| 766 | |
| 767 do { | |
| 768 if (input_string[in_posn] == '\\') { | |
| 769 if (in_posn + 1 >= length) { | |
| 770 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 236, "Incomplete escape character in input"); | |
| 771 } | |
| 772 ch = input_string[in_posn + 1]; | |
| 773 /* NOTE: if add escape character, must also update regex in "frontend_qt/datawindow.php" */ | |
| 774 switch (ch) { | |
| 775 case '0': | |
| 776 case 'E': | |
| 777 case 'a': | |
| 778 case 'b': | |
| 779 case 't': | |
| 780 case 'n': | |
| 781 case 'v': | |
| 782 case 'f': | |
| 783 case 'r': | |
| 784 case 'e': | |
| 785 case 'G': | |
| 786 case 'R': | |
| 787 case '\\': | |
| 788 if (escaped_string) escaped_string[out_posn] = vals[posn(escs, ch)]; | |
| 789 in_posn += 2; | |
| 790 break; | |
| 791 case '^': /* CODE128 specific */ | |
| 792 if (!extra_escape_mode) { | |
| 793 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 798, | |
| 794 "Escape '\\^' only valid for Code 128 in extra escape mode"); | |
| 795 } | |
| 796 /* Pass thru unaltered */ | |
| 797 if (escaped_string) { | |
| 798 escaped_string[out_posn++] = '\\'; | |
| 799 escaped_string[out_posn] = '^'; | |
| 800 } else { | |
| 801 out_posn++; | |
| 802 } | |
| 803 in_posn += 2; | |
| 804 if (in_posn < length) { /* Note allowing '\\^' on its own at end */ | |
| 805 if (escaped_string) { | |
| 806 escaped_string[++out_posn] = input_string[in_posn++]; | |
| 807 } else { | |
| 808 ++out_posn; | |
| 809 in_posn++; | |
| 810 } | |
| 811 } | |
| 812 break; | |
| 813 case 'd': | |
| 814 case 'o': | |
| 815 case 'x': | |
| 816 if ((val = esc_base(symbol, input_string, length, in_posn + 2, ch)) == -1) { | |
| 817 return ZINT_ERROR_INVALID_DATA; | |
| 818 } | |
| 819 if (escaped_string) escaped_string[out_posn] = val; | |
| 820 in_posn += 4 + (ch != 'x'); | |
| 821 break; | |
| 822 case 'u': | |
| 823 case 'U': | |
| 824 if (in_posn + 6 > length || (ch == 'U' && in_posn + 8 > length)) { | |
| 825 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 209, | |
| 826 "Incomplete '\\%c' escape sequence in input", ch); | |
| 827 } | |
| 828 unicode = 0; | |
| 829 for (i = 0; i < 6; i++) { | |
| 830 if ((val = ctoi(input_string[in_posn + i + 2])) == -1) { | |
| 831 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 211, | |
| 832 "Invalid character for '\\%c' escape sequence in input (hexadecimal only)", | |
| 833 ch); | |
| 834 } | |
| 835 unicode = (unicode << 4) | val; | |
| 836 if (i == 3 && ch == 'u') { | |
| 837 break; | |
| 838 } | |
| 839 } | |
| 840 /* Exclude reversed BOM and surrogates and out-of-range */ | |
| 841 if (unicode == 0xfffe || (unicode >= 0xd800 && unicode < 0xe000) || unicode > 0x10ffff) { | |
| 842 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 246, | |
| 843 "Value of escape sequence '%.*s' in input out of range", | |
| 844 ch == 'u' ? 6 : 8, input_string + in_posn); | |
| 845 } | |
| 846 if (unicode < 0x80) { | |
| 847 if (escaped_string) escaped_string[out_posn] = (unsigned char) unicode; | |
| 848 } else if (unicode < 0x800) { | |
| 849 if (escaped_string) { | |
| 850 escaped_string[out_posn++] = (unsigned char) (0xC0 | (unicode >> 6)); | |
| 851 escaped_string[out_posn] = (unsigned char) (0x80 | (unicode & 0x3F)); | |
| 852 } else { | |
| 853 out_posn++; | |
| 854 } | |
| 855 } else if (unicode < 0x10000) { | |
| 856 if (escaped_string) { | |
| 857 escaped_string[out_posn++] = (unsigned char) (0xE0 | (unicode >> 12)); | |
| 858 escaped_string[out_posn++] = (unsigned char) (0x80 | ((unicode >> 6) & 0x3F)); | |
| 859 escaped_string[out_posn] = (unsigned char) (0x80 | (unicode & 0x3F)); | |
| 860 } else { | |
| 861 out_posn += 2; | |
| 862 } | |
| 863 } else { | |
| 864 if (escaped_string) { | |
| 865 escaped_string[out_posn++] = (unsigned char) (0xF0 | (unicode >> 18)); | |
| 866 escaped_string[out_posn++] = (unsigned char) (0x80 | ((unicode >> 12) & 0x3F)); | |
| 867 escaped_string[out_posn++] = (unsigned char) (0x80 | ((unicode >> 6) & 0x3F)); | |
| 868 escaped_string[out_posn] = (unsigned char) (0x80 | (unicode & 0x3F)); | |
| 869 } else { | |
| 870 out_posn += 3; | |
| 871 } | |
| 872 } | |
| 873 in_posn += 6 + (ch == 'U') * 2; | |
| 874 break; | |
| 875 default: | |
| 876 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 234, | |
| 877 "Unrecognised escape character '\\%c' in input", ch); | |
| 878 break; | |
| 879 } | |
| 880 } else { | |
| 881 if (escaped_string) escaped_string[out_posn] = input_string[in_posn]; | |
| 882 in_posn++; | |
| 883 } | |
| 884 out_posn++; | |
| 885 } while (in_posn < length); | |
| 886 | |
| 887 if (escaped_string) { | |
| 888 escaped_string[out_posn] = '\0'; | |
| 889 } | |
| 890 *p_length = out_posn; | |
| 891 | |
| 892 return 0; | |
| 893 } | |
| 894 | |
| 895 #ifdef ZINT_TEST /* Wrapper for direct testing (also used by `testUtilZXingCPPCmp()` in "tests/testcommon.c") */ | |
| 896 INTERNAL int escape_char_process_test(struct zint_symbol *symbol, const unsigned char *input_string, int *p_length, | |
| 897 unsigned char *escaped_string) { | |
| 898 return escape_char_process(symbol, input_string, p_length, escaped_string); | |
| 899 } | |
| 900 #endif | |
| 901 | |
| 902 /* For backward-compatibility, map certain invalid symbol ids to zint equivalents, some silently, some with warning */ | |
| 903 static int map_invalid_symbology(struct zint_symbol *symbol) { | |
| 904 | |
| 905 /* Symbol ids 1 to 126 are defined by tbarcode */ | |
| 906 /* 26 allowed: UPC-A up to tbarcode 9, ISSN for tbarcode 10+, mapped to UPC-A */ | |
| 907 /* 27 error: UPCD1 up to tbarcode 9, ISSN + 2 digit add-on for tbarcode 10+ */ | |
| 908 /* 91 warning: BC412 up to tbarcode 9, Code 32 for tbarcode 10+, mapped to Code 128 */ | |
| 909 /* Note: non-zero table entries map silently, i.e. do not produce a warning */ | |
| 910 #define LIB_ID_MAP_LAST 111 | |
| 911 static const unsigned char id_map[LIB_ID_MAP_LAST + 1] = { | |
| 912 0, 0, 0, 0, 0, /*0-4*/ | |
| 913 BARCODE_C25STANDARD, 0, 0, 0, 0, /*5-9*/ | |
| 914 BARCODE_EANX, BARCODE_EANX, BARCODE_EANX, 0, 0, /*10-14*/ | |
| 915 BARCODE_EANX, 0, BARCODE_UPCA, 0, BARCODE_CODABAR, /*15-19*/ | |
| 916 0, 0, 0, 0, 0, /*20-24*/ | |
| 917 0, BARCODE_UPCA, 0, 0, 0, /*25-29*/ | |
| 918 0, 0, 0, BARCODE_GS1_128, 0, /*30-34*/ | |
| 919 0, BARCODE_UPCA, 0, 0, BARCODE_UPCE, /*35-39*/ | |
| 920 0, BARCODE_POSTNET, BARCODE_POSTNET, BARCODE_POSTNET, BARCODE_POSTNET, /*40-44*/ | |
| 921 BARCODE_POSTNET, BARCODE_PLESSEY, 0, BARCODE_NVE18, 0, /*45-49*/ | |
| 922 0, 0, 0, 0, 0, /*50-54*/ | |
| 923 0, 0, 0, 0, BARCODE_CODE128, /*55-59*/ | |
| 924 0, BARCODE_CODE128, BARCODE_CODE93, 0, BARCODE_AUSPOST, /*60-64*/ | |
| 925 BARCODE_AUSPOST, 0, 0, 0, 0, /*65-69*/ | |
| 926 0, 0, 0, 0, 0, /*70-74*/ | |
| 927 0, 0, 0, BARCODE_DBAR_OMN, 0, /*75-79*/ | |
| 928 0, 0, 0, BARCODE_PLANET, 0, /*80-84*/ | |
| 929 0, 0, 0, BARCODE_GS1_128, 0, /*85-89*/ | |
| 930 0, 0, 0, 0, 0, /*90-94*/ | |
| 931 0, 0, 0, 0, 0, /*95-99*/ | |
| 932 BARCODE_HIBC_128, BARCODE_HIBC_39, 0, BARCODE_HIBC_DM, 0, /*100-104*/ | |
| 933 BARCODE_HIBC_QR, 0, BARCODE_HIBC_PDF, 0, BARCODE_HIBC_MICPDF, /*105-109*/ | |
| 934 0, BARCODE_HIBC_BLOCKF, /*110-111*/ | |
| 935 }; | |
| 936 const int orig_symbology = symbol->symbology; /* For self-check */ | |
| 937 int warn_number = 0; | |
| 938 | |
| 939 if (symbol->symbology == 19) { | |
| 940 /* Has specific error message */ | |
| 941 warn_number = error_tag(ZINT_WARN_INVALID_OPTION, symbol, 207, "Codabar 18 not supported"); | |
| 942 if (warn_number >= ZINT_ERROR) { | |
| 943 return warn_number; | |
| 944 } | |
| 945 symbol->symbology = BARCODE_CODABAR; | |
| 946 } else if (symbol->symbology == 27) { | |
| 947 /* Not mapped */ | |
| 948 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 208, "UPCD1 not supported"); | |
| 949 | |
| 950 } else if (symbol->symbology <= 0 || symbol->symbology > LIB_ID_MAP_LAST || id_map[symbol->symbology] == 0) { | |
| 951 warn_number = error_tag(ZINT_WARN_INVALID_OPTION, symbol, 206, "Symbology out of range"); | |
| 952 if (warn_number >= ZINT_ERROR) { | |
| 953 return warn_number; | |
| 954 } | |
| 955 symbol->symbology = BARCODE_CODE128; | |
| 956 } else { | |
| 957 symbol->symbology = id_map[symbol->symbology]; | |
| 958 } | |
| 959 | |
| 960 if (symbol->symbology == orig_symbology) { /* Should never happen */ | |
| 961 assert(0); /* Not reached */ | |
| 962 return error_tag(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0, "Internal error"); | |
| 963 } | |
| 964 | |
| 965 return warn_number; | |
| 966 } | |
| 967 | |
| 968 /* Encode a barcode. If `length` is 0, `source` must be NUL-terminated */ | |
| 969 int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length) { | |
| 970 struct zint_seg segs[1]; | |
| 971 | |
| 972 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 973 | |
| 974 segs[0].eci = symbol->eci; | |
| 975 segs[0].source = (unsigned char *) source; | |
| 976 segs[0].length = length; | |
| 977 | |
| 978 return ZBarcode_Encode_Segs(symbol, segs, 1); | |
| 979 } | |
| 980 | |
| 981 /* Encode a barcode with multiple ECI segments. */ | |
| 982 int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count) { | |
| 983 int error_number, warn_number = 0; | |
| 984 int total_len = 0; | |
| 985 int have_zero_eci = 0; | |
| 986 int escape_mode; | |
| 987 int i; | |
| 988 unsigned char *local_source; | |
| 989 struct zint_seg *local_segs; | |
| 990 unsigned char *local_sources; | |
| 991 | |
| 992 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 993 | |
| 994 if (segs == NULL) { | |
| 995 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 200, "Input segments NULL"); | |
| 996 } | |
| 997 /* `seg_count` zero dealt with via `total_len` zero below */ | |
| 998 if (seg_count > ZINT_MAX_SEG_COUNT) { | |
| 999 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 771, "Too many input segments (maximum 256)"); | |
| 1000 } | |
| 1001 | |
| 1002 if ((symbol->input_mode & 0x07) > 2) { | |
| 1003 symbol->input_mode = DATA_MODE; /* Reset completely */ | |
| 1004 warn_number = error_tag(ZINT_WARN_INVALID_OPTION, symbol, 212, "Invalid input mode - reset to DATA_MODE"); | |
| 1005 if (warn_number >= ZINT_ERROR) { | |
| 1006 return warn_number; | |
| 1007 } | |
| 1008 } | |
| 1009 | |
| 1010 /* Check the symbology field */ | |
| 1011 if (!ZBarcode_ValidID(symbol->symbology)) { | |
| 1012 warn_number = map_invalid_symbology(symbol); | |
| 1013 if (warn_number >= ZINT_ERROR) { | |
| 1014 return warn_number; | |
| 1015 } | |
| 1016 } | |
| 1017 | |
| 1018 escape_mode = (symbol->input_mode & ESCAPE_MODE) | |
| 1019 || ((symbol->input_mode & EXTRA_ESCAPE_MODE) && symbol->symbology == BARCODE_CODE128); | |
| 1020 | |
| 1021 local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * (seg_count > 0 ? seg_count : 1)); | |
| 1022 | |
| 1023 /* Check segment lengths */ | |
| 1024 for (i = 0; i < seg_count; i++) { | |
| 1025 local_segs[i] = segs[i]; | |
| 1026 if (local_segs[i].source == NULL) { | |
| 1027 errtxtf(0, symbol, 772, "Input segment %d source NULL", i); | |
| 1028 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1029 } | |
| 1030 if (local_segs[i].length <= 0) { | |
| 1031 local_segs[i].length = (int) ustrlen(local_segs[i].source); | |
| 1032 } | |
| 1033 if (local_segs[i].length <= 0) { | |
| 1034 if (i == 0) { | |
| 1035 if (is_composite(symbol->symbology) | |
| 1036 && ((symbol->input_mode & 0x07) == GS1_MODE || check_force_gs1(symbol->symbology))) { | |
| 1037 errtxt(0, symbol, 779, "No composite data (2D component)"); | |
| 1038 } else if (supports_eci(symbol->symbology)) { | |
| 1039 errtxt(0, symbol, 228, "No input data (segment 0 empty)"); | |
| 1040 } else { | |
| 1041 errtxt(0, symbol, 778, "No input data"); | |
| 1042 } | |
| 1043 } else { | |
| 1044 errtxtf(0, symbol, 773, "Input segment %d empty", i); | |
| 1045 } | |
| 1046 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1047 } | |
| 1048 /* Calculate de-escaped length for check against ZINT_MAX_DATA_LEN */ | |
| 1049 if (escape_mode) { | |
| 1050 int escaped_len = local_segs[i].length; | |
| 1051 error_number = escape_char_process(symbol, local_segs[i].source, &escaped_len, NULL /*escaped_string*/); | |
| 1052 if (error_number != 0) { /* Only returns errors, not warnings */ | |
| 1053 return error_tag(error_number, symbol, -1, NULL); | |
| 1054 } | |
| 1055 if (escaped_len > ZINT_MAX_DATA_LEN) { | |
| 1056 return error_tag(ZINT_ERROR_TOO_LONG, symbol, 797, "Input too long"); | |
| 1057 } | |
| 1058 total_len += escaped_len; | |
| 1059 } else { | |
| 1060 if (local_segs[i].length > ZINT_MAX_DATA_LEN) { | |
| 1061 return error_tag(ZINT_ERROR_TOO_LONG, symbol, 777, "Input too long"); | |
| 1062 } | |
| 1063 total_len += local_segs[i].length; | |
| 1064 } | |
| 1065 } | |
| 1066 | |
| 1067 if (total_len == 0) { | |
| 1068 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 205, "No input data"); | |
| 1069 } | |
| 1070 | |
| 1071 if (symbol->debug & ZINT_DEBUG_PRINT) { | |
| 1072 const int len = local_segs[0].length; | |
| 1073 const int primary_len = symbol->primary[0] ? (int) strlen(symbol->primary) : 0; | |
| 1074 char name[32]; | |
| 1075 char source[151], primary[151]; /* 30*5 + 1 = 151 */ | |
| 1076 (void) ZBarcode_BarcodeName(symbol->symbology, name); | |
| 1077 debug_print_escape(local_segs[0].source, len > 30 ? 30 : len, source); | |
| 1078 debug_print_escape((const unsigned char *) symbol->primary, primary_len > 30 ? 30 : primary_len, primary); | |
| 1079 printf("\nZBarcode_Encode_Segs: %s (%d), input_mode: 0x%X, ECI: %d, option_1/2/3: (%d, %d, %d)\n" | |
| 1080 " scale: %g, output_options: 0x%X, fg: %s, bg: %s, seg_count: %d,\n" | |
| 1081 " %ssource%s (%d): \"%s\",\n" | |
| 1082 " %sprimary (%d): \"%s\"\n", | |
| 1083 name, symbol->symbology, symbol->input_mode, symbol->eci, symbol->option_1, symbol->option_2, | |
| 1084 symbol->option_3, symbol->scale, symbol->output_options, symbol->fgcolour, symbol->bgcolour, | |
| 1085 seg_count, len > 30 ? "first 30 " : "", seg_count > 1 ? "[0]" : "", len, source, | |
| 1086 primary_len > 30 ? "first 30 " : "", primary_len, primary); | |
| 1087 fflush(stdout); | |
| 1088 } | |
| 1089 | |
| 1090 if (total_len > ZINT_MAX_DATA_LEN) { | |
| 1091 return error_tag(ZINT_ERROR_TOO_LONG, symbol, 243, "Input too long"); | |
| 1092 } | |
| 1093 | |
| 1094 /* Reconcile symbol ECI and first segment ECI if both set */ | |
| 1095 if (symbol->eci != local_segs[0].eci) { | |
| 1096 if (symbol->eci && local_segs[0].eci) { | |
| 1097 errtxtf(0, symbol, 774, "Symbol ECI '%1$d' must match segment zero ECI '%2$d'", | |
| 1098 symbol->eci, local_segs[0].eci); | |
| 1099 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, -1, NULL); | |
| 1100 } | |
| 1101 if (symbol->eci) { | |
| 1102 local_segs[0].eci = symbol->eci; | |
| 1103 } else { | |
| 1104 symbol->eci = local_segs[0].eci; | |
| 1105 } | |
| 1106 } | |
| 1107 | |
| 1108 if (seg_count > 1 && !supports_eci(symbol->symbology)) { | |
| 1109 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 775, "Symbology does not support multiple segments"); | |
| 1110 } | |
| 1111 | |
| 1112 /* Check ECI(s) */ | |
| 1113 for (i = 0; i < seg_count; i++) { | |
| 1114 if (local_segs[i].eci) { | |
| 1115 if (!supports_eci(symbol->symbology)) { | |
| 1116 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 217, "Symbology does not support ECI switching"); | |
| 1117 } | |
| 1118 if (local_segs[i].eci < 0 || local_segs[i].eci == 1 || local_segs[i].eci == 2 || local_segs[i].eci == 14 | |
| 1119 || local_segs[i].eci == 19 || local_segs[i].eci > 999999) { | |
| 1120 errtxtf(0, symbol, 218, "ECI code '%d' out of range (0 to 999999, excluding 1, 2, 14 and 19)", | |
| 1121 local_segs[i].eci); | |
| 1122 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, -1, NULL); | |
| 1123 } | |
| 1124 } else { | |
| 1125 have_zero_eci = 1; | |
| 1126 } | |
| 1127 } | |
| 1128 | |
| 1129 /* Check other symbol fields */ | |
| 1130 if ((symbol->scale < 0.01f) || (symbol->scale > 200.0f)) { | |
| 1131 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 227, "Scale out of range (0.01 to 200)"); | |
| 1132 } | |
| 1133 if ((symbol->dot_size < 0.01f) || (symbol->dot_size > 20.0f)) { | |
| 1134 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 221, "Dot size out of range (0.01 to 20)"); | |
| 1135 } | |
| 1136 | |
| 1137 if ((symbol->height < 0.0f) || (symbol->height > 2000.0f)) { /* Allow for 44 row CODABLOCKF at 45X each */ | |
| 1138 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 765, "Height out of range (0 to 2000)"); | |
| 1139 } | |
| 1140 if ((symbol->guard_descent < 0.0f) || (symbol->guard_descent > 50.0f)) { | |
| 1141 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 769, "Guard bar descent out of range (0 to 50)"); | |
| 1142 } | |
| 1143 if ((symbol->text_gap < -5.0f) || (symbol->text_gap > 10.0f)) { | |
| 1144 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 219, "Text gap out of range (-5 to 10)"); | |
| 1145 } | |
| 1146 if ((symbol->whitespace_width < 0) || (symbol->whitespace_width > 100)) { | |
| 1147 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 766, "Whitespace width out of range (0 to 100)"); | |
| 1148 } | |
| 1149 if ((symbol->whitespace_height < 0) || (symbol->whitespace_height > 100)) { | |
| 1150 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 767, "Whitespace height out of range (0 to 100)"); | |
| 1151 } | |
| 1152 if ((symbol->border_width < 0) || (symbol->border_width > 100)) { | |
| 1153 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 768, "Border width out of range (0 to 100)"); | |
| 1154 } | |
| 1155 | |
| 1156 if (symbol->rows >= 200) { /* Check for stacking too many symbols */ | |
| 1157 return error_tag(ZINT_ERROR_TOO_LONG, symbol, 770, "Too many stacked symbols"); | |
| 1158 } | |
| 1159 if (symbol->rows < 0) { /* Silently defend against out-of-bounds access */ | |
| 1160 symbol->rows = 0; | |
| 1161 } | |
| 1162 | |
| 1163 if ((symbol->input_mode & 0x07) == GS1_MODE && !gs1_compliant(symbol->symbology)) { | |
| 1164 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 220, "Selected symbology does not support GS1 mode"); | |
| 1165 } | |
| 1166 if (seg_count > 1) { | |
| 1167 /* Note: GS1_MODE not currently supported when using multiple segments */ | |
| 1168 if ((symbol->input_mode & 0x07) == GS1_MODE) { | |
| 1169 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 776, "GS1 mode not supported for multiple segments"); | |
| 1170 } | |
| 1171 } | |
| 1172 | |
| 1173 local_sources = (unsigned char *) z_alloca(total_len + seg_count); | |
| 1174 | |
| 1175 /* Copy input, de-escaping if required */ | |
| 1176 for (i = 0, local_source = local_sources; i < seg_count; i++) { | |
| 1177 local_segs[i].source = local_source; | |
| 1178 if (escape_mode) { | |
| 1179 /* Checked already */ | |
| 1180 (void) escape_char_process(symbol, segs[i].source, &local_segs[i].length, local_segs[i].source); | |
| 1181 } else { | |
| 1182 memcpy(local_segs[i].source, segs[i].source, local_segs[i].length); | |
| 1183 local_segs[i].source[local_segs[i].length] = '\0'; | |
| 1184 } | |
| 1185 local_source += local_segs[i].length + 1; | |
| 1186 } | |
| 1187 | |
| 1188 if (escape_mode && symbol->primary[0] && strchr(symbol->primary, '\\') != NULL) { | |
| 1189 char primary[sizeof(symbol->primary)]; | |
| 1190 int primary_len = (int) strlen(symbol->primary); | |
| 1191 if (primary_len >= (int) sizeof(symbol->primary)) { | |
| 1192 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 799, "Invalid primary string"); | |
| 1193 } | |
| 1194 ustrcpy(primary, symbol->primary); | |
| 1195 error_number = escape_char_process(symbol, (unsigned char *) primary, &primary_len, | |
| 1196 (unsigned char *) symbol->primary); | |
| 1197 if (error_number != 0) { /* Only returns errors, not warnings */ | |
| 1198 return error_tag(error_number, symbol, -1, NULL); | |
| 1199 } | |
| 1200 } | |
| 1201 | |
| 1202 if ((symbol->input_mode & 0x07) == UNICODE_MODE) { | |
| 1203 for (i = 0; i < seg_count; i++) { | |
| 1204 if (!is_valid_utf8(local_segs[i].source, local_segs[i].length)) { | |
| 1205 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 245, "Invalid UTF-8 in input"); | |
| 1206 } | |
| 1207 } | |
| 1208 /* Only strip BOM on first segment */ | |
| 1209 strip_bom(local_segs[0].source, &local_segs[0].length); | |
| 1210 } | |
| 1211 | |
| 1212 if (((symbol->input_mode & 0x07) == GS1_MODE) || (check_force_gs1(symbol->symbology))) { | |
| 1213 if (gs1_compliant(symbol->symbology)) { | |
| 1214 /* Reduce input for composite and non-forced symbologies, others (EAN128 and RSS_EXP based) will | |
| 1215 handle it themselves */ | |
| 1216 if (is_composite(symbol->symbology) || !check_force_gs1(symbol->symbology)) { | |
| 1217 unsigned char *reduced = (unsigned char *) z_alloca(local_segs[0].length + 1); | |
| 1218 error_number = gs1_verify(symbol, local_segs[0].source, local_segs[0].length, reduced); | |
| 1219 if (error_number) { | |
| 1220 if (is_composite(symbol->symbology)) { | |
| 1221 errtxt_adj(0, symbol, "%1$s%2$s", " (2D component)"); | |
| 1222 } | |
| 1223 error_number = error_tag(error_number, symbol, -1, NULL); | |
| 1224 if (error_number >= ZINT_ERROR) { | |
| 1225 return error_number; | |
| 1226 } | |
| 1227 warn_number = error_number; /* Override any previous warning (errtxt has been overwritten) */ | |
| 1228 } | |
| 1229 ustrcpy(local_segs[0].source, reduced); /* Cannot contain NUL char */ | |
| 1230 local_segs[0].length = (int) ustrlen(reduced); | |
| 1231 } | |
| 1232 } else { | |
| 1233 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 210, "Selected symbology does not support GS1 mode"); | |
| 1234 } | |
| 1235 } | |
| 1236 | |
| 1237 error_number = extended_or_reduced_charset(symbol, local_segs, seg_count); | |
| 1238 | |
| 1239 if ((error_number == ZINT_ERROR_INVALID_DATA) && have_zero_eci && supports_eci(symbol->symbology) | |
| 1240 && (symbol->input_mode & 0x07) == UNICODE_MODE) { | |
| 1241 /* Try another ECI mode */ | |
| 1242 const int first_eci_set = get_best_eci_segs(symbol, local_segs, seg_count); | |
| 1243 error_number = extended_or_reduced_charset(symbol, local_segs, seg_count); | |
| 1244 /* Inclusion of ECI more noteworthy than other warnings, so overwrite (if any) */ | |
| 1245 if (error_number < ZINT_ERROR) { | |
| 1246 error_number = ZINT_WARN_USES_ECI; | |
| 1247 if (!(symbol->debug & ZINT_DEBUG_TEST)) { | |
| 1248 errtxtf(0, symbol, 222, "Encoded data includes ECI %d", first_eci_set); | |
| 1249 } | |
| 1250 if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", first_eci_set); | |
| 1251 } | |
| 1252 } | |
| 1253 | |
| 1254 if (error_number == 0) { | |
| 1255 error_number = warn_number; /* Already tagged */ | |
| 1256 } else { | |
| 1257 error_number = error_tag(error_number, symbol, -1, NULL); | |
| 1258 } | |
| 1259 | |
| 1260 if (error_number < ZINT_ERROR) { | |
| 1261 if (symbol->height < 0.5f) { /* Absolute minimum */ | |
| 1262 (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); | |
| 1263 } | |
| 1264 } | |
| 1265 | |
| 1266 return error_number; | |
| 1267 } | |
| 1268 | |
| 1269 /* Helper for output routines to check `rotate_angle` and dottiness */ | |
| 1270 static int check_output_args(struct zint_symbol *symbol, int rotate_angle) { | |
| 1271 | |
| 1272 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 1273 | |
| 1274 switch (rotate_angle) { | |
| 1275 case 0: | |
| 1276 case 90: | |
| 1277 case 180: | |
| 1278 case 270: | |
| 1279 break; | |
| 1280 default: | |
| 1281 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 223, "Invalid rotation angle"); | |
| 1282 break; | |
| 1283 } | |
| 1284 | |
| 1285 if ((symbol->output_options & BARCODE_DOTTY_MODE) && !(is_dotty(symbol->symbology))) { | |
| 1286 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 224, "Selected symbology cannot be rendered as dots"); | |
| 1287 } | |
| 1288 | |
| 1289 return 0; | |
| 1290 } | |
| 1291 | |
| 1292 static const struct { const char extension[4]; int is_raster; int filetype; } filetypes[] = { | |
| 1293 { "BMP", 1, OUT_BMP_FILE }, { "EMF", 0, OUT_EMF_FILE }, { "EPS", 0, OUT_EPS_FILE }, | |
| 1294 { "GIF", 1, OUT_GIF_FILE }, { "PCX", 1, OUT_PCX_FILE }, { "PNG", 1, OUT_PNG_FILE }, | |
| 1295 { "SVG", 0, OUT_SVG_FILE }, { "TIF", 1, OUT_TIF_FILE }, { "TXT", 0, 0 } | |
| 1296 }; | |
| 1297 | |
| 1298 /* Return index of `extension` in `filetypes`, or -1 if not found */ | |
| 1299 static int filetype_idx(const char *extension) { | |
| 1300 char uc_extension[4] = {0}; | |
| 1301 int i; | |
| 1302 | |
| 1303 if (strlen(extension) != 3) { | |
| 1304 return -1; | |
| 1305 } | |
| 1306 memcpy(uc_extension, extension, 3); | |
| 1307 to_upper((unsigned char *) uc_extension, 3); | |
| 1308 | |
| 1309 for (i = 0; i < ARRAY_SIZE(filetypes); i++) { | |
| 1310 if (strcmp(uc_extension, filetypes[i].extension) == 0) { | |
| 1311 break; | |
| 1312 } | |
| 1313 } | |
| 1314 | |
| 1315 return i == ARRAY_SIZE(filetypes) ? -1 : i; | |
| 1316 } | |
| 1317 | |
| 1318 /* Output a previously encoded symbol to file `symbol->outfile` */ | |
| 1319 int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { | |
| 1320 int error_number; | |
| 1321 int len; | |
| 1322 | |
| 1323 if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ | |
| 1324 return error_number; /* Already tagged */ | |
| 1325 } | |
| 1326 | |
| 1327 len = (int) strlen(symbol->outfile); | |
| 1328 if (len > 3) { | |
| 1329 int i = filetype_idx(symbol->outfile + len - 3); | |
| 1330 if (i >= 0) { | |
| 1331 if (filetypes[i].filetype) { | |
| 1332 if (filetypes[i].is_raster) { | |
| 1333 error_number = plot_raster(symbol, rotate_angle, filetypes[i].filetype); | |
| 1334 } else { | |
| 1335 error_number = plot_vector(symbol, rotate_angle, filetypes[i].filetype); | |
| 1336 } | |
| 1337 } else { | |
| 1338 error_number = dump_plot(symbol); | |
| 1339 } | |
| 1340 } else { | |
| 1341 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 225, "Unknown output format"); | |
| 1342 } | |
| 1343 } else { | |
| 1344 return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 226, "Unknown output format"); | |
| 1345 } | |
| 1346 | |
| 1347 return error_tag(error_number, symbol, -1, NULL); | |
| 1348 } | |
| 1349 | |
| 1350 /* Output a previously encoded symbol to memory as raster (`symbol->bitmap`) */ | |
| 1351 int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { | |
| 1352 int error_number; | |
| 1353 | |
| 1354 if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ | |
| 1355 return error_number; /* Already tagged */ | |
| 1356 } | |
| 1357 | |
| 1358 error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER); | |
| 1359 return error_tag(error_number, symbol, -1, NULL); | |
| 1360 } | |
| 1361 | |
| 1362 /* Output a previously encoded symbol to memory as vector (`symbol->vector`) */ | |
| 1363 int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { | |
| 1364 int error_number; | |
| 1365 | |
| 1366 if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ | |
| 1367 return error_number; /* Already tagged */ | |
| 1368 } | |
| 1369 | |
| 1370 error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER); | |
| 1371 return error_tag(error_number, symbol, -1, NULL); | |
| 1372 } | |
| 1373 | |
| 1374 /* Encode and output a symbol to file `symbol->outfile` */ | |
| 1375 int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle) { | |
| 1376 struct zint_seg segs[1]; | |
| 1377 | |
| 1378 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 1379 | |
| 1380 segs[0].eci = symbol->eci; | |
| 1381 segs[0].source = (unsigned char *) source; | |
| 1382 segs[0].length = length; | |
| 1383 | |
| 1384 return ZBarcode_Encode_Segs_and_Print(symbol, segs, 1, rotate_angle); | |
| 1385 } | |
| 1386 | |
| 1387 /* Encode a symbol with multiple ECI segments and output to file `symbol->outfile` */ | |
| 1388 int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count, | |
| 1389 int rotate_angle) { | |
| 1390 int error_number; | |
| 1391 int warn_number; | |
| 1392 | |
| 1393 warn_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); | |
| 1394 if (warn_number >= ZINT_ERROR) { | |
| 1395 return warn_number; | |
| 1396 } | |
| 1397 | |
| 1398 error_number = ZBarcode_Print(symbol, rotate_angle); | |
| 1399 | |
| 1400 return error_number ? error_number : warn_number; | |
| 1401 } | |
| 1402 | |
| 1403 /* Encode and output a symbol to memory as raster (`symbol->bitmap`) */ | |
| 1404 int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *source, int length, | |
| 1405 int rotate_angle) { | |
| 1406 struct zint_seg segs[1]; | |
| 1407 | |
| 1408 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 1409 | |
| 1410 segs[0].eci = symbol->eci; | |
| 1411 segs[0].source = (unsigned char *) source; | |
| 1412 segs[0].length = length; | |
| 1413 | |
| 1414 return ZBarcode_Encode_Segs_and_Buffer(symbol, segs, 1, rotate_angle); | |
| 1415 } | |
| 1416 | |
| 1417 /* Encode a symbol with multiple ECI segments and output to memory as raster (`symbol->bitmap`) */ | |
| 1418 int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, const struct zint_seg segs[], | |
| 1419 const int seg_count, int rotate_angle) { | |
| 1420 int error_number; | |
| 1421 int warn_number; | |
| 1422 | |
| 1423 warn_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); | |
| 1424 if (warn_number >= ZINT_ERROR) { | |
| 1425 return warn_number; | |
| 1426 } | |
| 1427 | |
| 1428 error_number = ZBarcode_Buffer(symbol, rotate_angle); | |
| 1429 | |
| 1430 return error_number ? error_number : warn_number; | |
| 1431 } | |
| 1432 | |
| 1433 /* Encode and output a symbol to memory as vector (`symbol->vector`) */ | |
| 1434 int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, const unsigned char *source, int length, | |
| 1435 int rotate_angle) { | |
| 1436 struct zint_seg segs[1]; | |
| 1437 | |
| 1438 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 1439 | |
| 1440 segs[0].eci = symbol->eci; | |
| 1441 segs[0].source = (unsigned char *) source; | |
| 1442 segs[0].length = length; | |
| 1443 | |
| 1444 return ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, segs, 1, rotate_angle); | |
| 1445 } | |
| 1446 | |
| 1447 /* Encode a symbol with multiple ECI segments and output to memory as vector (`symbol->vector`) */ | |
| 1448 int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, const struct zint_seg segs[], | |
| 1449 const int seg_count, int rotate_angle) { | |
| 1450 int error_number; | |
| 1451 int warn_number; | |
| 1452 | |
| 1453 warn_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); | |
| 1454 if (warn_number >= ZINT_ERROR) { | |
| 1455 return warn_number; | |
| 1456 } | |
| 1457 | |
| 1458 error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle); | |
| 1459 | |
| 1460 return error_number ? error_number : warn_number; | |
| 1461 } | |
| 1462 | |
| 1463 /* Encode a barcode using input data from file `filename` */ | |
| 1464 int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) { | |
| 1465 FILE *file; | |
| 1466 int file_opened = 0; | |
| 1467 unsigned char *buffer; | |
| 1468 long fileLen; | |
| 1469 size_t n; | |
| 1470 size_t nRead = 0; | |
| 1471 int ret; | |
| 1472 | |
| 1473 if (!symbol) return ZINT_ERROR_INVALID_DATA; | |
| 1474 | |
| 1475 if (!filename) { | |
| 1476 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 239, "Filename NULL"); | |
| 1477 } | |
| 1478 | |
| 1479 if (strcmp(filename, "-") == 0) { | |
| 1480 file = stdin; | |
| 1481 fileLen = ZINT_MAX_DATA_LEN; | |
| 1482 } else { | |
| 1483 #ifdef _WIN32 | |
| 1484 file = out_win_fopen(filename, "rb"); | |
| 1485 #else | |
| 1486 file = fopen(filename, "rb"); | |
| 1487 #endif | |
| 1488 if (!file) { | |
| 1489 errtxtf(0, symbol, 229, "Unable to read input file (%1$d: %2$s)", errno, strerror(errno)); | |
| 1490 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1491 } | |
| 1492 file_opened = 1; | |
| 1493 | |
| 1494 /* Get file length */ | |
| 1495 if (fseek(file, 0, SEEK_END) != 0) { | |
| 1496 errtxtf(0, symbol, 797, "Unable to seek input file (%1$d: %2$s)", errno, strerror(errno)); | |
| 1497 (void) fclose(file); | |
| 1498 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1499 } | |
| 1500 | |
| 1501 fileLen = ftell(file); | |
| 1502 | |
| 1503 /* On many Linux distros `ftell()` returns LONG_MAX not -1 on error */ | |
| 1504 if (fileLen <= 0 || fileLen == LONG_MAX) { | |
| 1505 (void) fclose(file); | |
| 1506 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 235, "Input file empty or unseekable"); | |
| 1507 } | |
| 1508 if (fileLen > ZINT_MAX_DATA_LEN) { | |
| 1509 (void) fclose(file); | |
| 1510 return error_tag(ZINT_ERROR_TOO_LONG, symbol, 230, "Input file too long"); | |
| 1511 } | |
| 1512 | |
| 1513 if (fseek(file, 0, SEEK_SET) != 0) { | |
| 1514 errtxtf(0, symbol, 793, "Unable to seek input file (%1$d: %2$s)", errno, strerror(errno)); | |
| 1515 (void) fclose(file); | |
| 1516 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1517 } | |
| 1518 } | |
| 1519 | |
| 1520 /* Allocate memory */ | |
| 1521 buffer = (unsigned char *) malloc(fileLen); | |
| 1522 if (!buffer) { | |
| 1523 if (file_opened) { | |
| 1524 (void) fclose(file); | |
| 1525 } | |
| 1526 return error_tag(ZINT_ERROR_MEMORY, symbol, 231, "Insufficient memory for file read buffer"); | |
| 1527 } | |
| 1528 | |
| 1529 /* Read file contents into buffer */ | |
| 1530 | |
| 1531 do { | |
| 1532 n = fread(buffer + nRead, 1, fileLen - nRead, file); | |
| 1533 if (ferror(file)) { | |
| 1534 errtxtf(0, symbol, 241, "Input file read error (%1$d: %2$s)", errno, strerror(errno)); | |
| 1535 free(buffer); | |
| 1536 if (file_opened) { | |
| 1537 (void) fclose(file); | |
| 1538 } | |
| 1539 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1540 } | |
| 1541 nRead += n; | |
| 1542 } while (!feof(file) && (0 < n) && ((long) nRead < fileLen)); | |
| 1543 | |
| 1544 if (file_opened) { | |
| 1545 if (fclose(file) != 0) { | |
| 1546 errtxtf(0, symbol, 794, "Failure on closing input file (%1$d: %2$s)", errno, strerror(errno)); | |
| 1547 free(buffer); | |
| 1548 return error_tag(ZINT_ERROR_INVALID_DATA, symbol, -1, NULL); | |
| 1549 } | |
| 1550 } | |
| 1551 ret = ZBarcode_Encode(symbol, buffer, (int) nRead); | |
| 1552 free(buffer); | |
| 1553 return ret; | |
| 1554 } | |
| 1555 | |
| 1556 /* Encode a symbol using input data from file `filename` and output to file `symbol->outfile` */ | |
| 1557 int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, const char *filename, int rotate_angle) { | |
| 1558 int error_number; | |
| 1559 int warn_number; | |
| 1560 | |
| 1561 warn_number = ZBarcode_Encode_File(symbol, filename); | |
| 1562 if (warn_number >= ZINT_ERROR) { | |
| 1563 return warn_number; | |
| 1564 } | |
| 1565 | |
| 1566 error_number = ZBarcode_Print(symbol, rotate_angle); | |
| 1567 | |
| 1568 return error_number ? error_number : warn_number; | |
| 1569 } | |
| 1570 | |
| 1571 /* Encode a symbol using input data from file `filename` and output to memory as raster (`symbol->bitmap`) */ | |
| 1572 int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char const *filename, int rotate_angle) { | |
| 1573 int error_number; | |
| 1574 int warn_number; | |
| 1575 | |
| 1576 warn_number = ZBarcode_Encode_File(symbol, filename); | |
| 1577 if (warn_number >= ZINT_ERROR) { | |
| 1578 return warn_number; | |
| 1579 } | |
| 1580 | |
| 1581 error_number = ZBarcode_Buffer(symbol, rotate_angle); | |
| 1582 | |
| 1583 return error_number ? error_number : warn_number; | |
| 1584 } | |
| 1585 | |
| 1586 /* Encode a symbol using input data from file `filename` and output to memory as vector (`symbol->vector`) */ | |
| 1587 int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const char *filename, int rotate_angle) { | |
| 1588 int error_number; | |
| 1589 int warn_number; | |
| 1590 | |
| 1591 warn_number = ZBarcode_Encode_File(symbol, filename); | |
| 1592 if (warn_number >= ZINT_ERROR) { | |
| 1593 return warn_number; | |
| 1594 } | |
| 1595 | |
| 1596 error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle); | |
| 1597 | |
| 1598 return error_number ? error_number : warn_number; | |
| 1599 } | |
| 1600 | |
| 1601 /* Checks whether a symbology is supported */ | |
| 1602 int ZBarcode_ValidID(int symbol_id) { | |
| 1603 | |
| 1604 if (symbol_id <= 0 || symbol_id > BARCODE_LAST) { | |
| 1605 return 0; | |
| 1606 } | |
| 1607 | |
| 1608 return barcode_src_funcs[symbol_id] != NULL | |
| 1609 || (symbol_id >= LIB_SEG_FUNCS_START && barcode_seg_funcs[symbol_id - LIB_SEG_FUNCS_START] != NULL); | |
| 1610 } | |
| 1611 | |
| 1612 /* Copy BARCODE_XXX name of `symbol_id` into `name` buffer, NUL-terminated. | |
| 1613 Returns 0 if valid, 1 if not valid */ | |
| 1614 int ZBarcode_BarcodeName(int symbol_id, char name[32]) { | |
| 1615 static const char *const names[] = { | |
| 1616 "", "CODE11", "C25STANDARD", "C25INTER", "C25IATA", /*0-4*/ | |
| 1617 "", "C25LOGIC", "C25IND", "CODE39", "EXCODE39", /*5-9*/ | |
| 1618 "", "", "", "EANX", "EANX_CHK", /*10-14*/ | |
| 1619 "", "GS1_128", "", "CODABAR", "", /*15-19*/ | |
| 1620 "CODE128", "DPLEIT", "DPIDENT", "CODE16K", "CODE49", /*20-24*/ | |
| 1621 "CODE93", "", "", "FLAT", "DBAR_OMN", /*25-29*/ | |
| 1622 "DBAR_LTD", "DBAR_EXP", "TELEPEN", "", "UPCA", /*30-34*/ | |
| 1623 "UPCA_CHK", "", "UPCE", "UPCE_CHK", "", /*35-39*/ | |
| 1624 "POSTNET", "", "", "", "", /*40-44*/ | |
| 1625 "", "", "MSI_PLESSEY", "", "FIM", /*45-49*/ | |
| 1626 "LOGMARS", "PHARMA", "PZN", "PHARMA_TWO", "CEPNET", /*50-54*/ | |
| 1627 "PDF417", "PDF417COMP", "MAXICODE", "QRCODE", "", /*55-59*/ | |
| 1628 "CODE128AB", "", "", "AUSPOST", "", /*60-64*/ | |
| 1629 "", "AUSREPLY", "AUSROUTE", "AUSREDIRECT", "ISBNX", /*65-69*/ | |
| 1630 "RM4SCC", "DATAMATRIX", "EAN14", "VIN", "CODABLOCKF", /*70-74*/ | |
| 1631 "NVE18", "JAPANPOST", "KOREAPOST", "", "DBAR_STK", /*75-79*/ | |
| 1632 "DBAR_OMNSTK", "DBAR_EXPSTK", "PLANET", "", "MICROPDF417", /*80-84*/ | |
| 1633 "USPS_IMAIL", "PLESSEY", "TELEPEN_NUM", "", "ITF14", /*85-89*/ | |
| 1634 "KIX", "", "AZTEC", "DAFT", "", /*90-94*/ | |
| 1635 "", "DPD", "MICROQR", "HIBC_128", "HIBC_39", /*95-99*/ | |
| 1636 "", "", "HIBC_DM", "", "HIBC_QR", /*100-104*/ | |
| 1637 "", "HIBC_PDF", "", "HIBC_MICPDF", "", /*105-109*/ | |
| 1638 "HIBC_BLOCKF", "", "HIBC_AZTEC", "", "", /*110-114*/ | |
| 1639 "DOTCODE", "HANXIN", "", "", "MAILMARK_2D", /*115-119*/ | |
| 1640 "UPU_S10", "MAILMARK_4S", "", "", "", /*120-124*/ | |
| 1641 "", "", "", "AZRUNE", "CODE32", /*125-129*/ | |
| 1642 "EANX_CC", "GS1_128_CC", "DBAR_OMN_CC", "DBAR_LTD_CC", "DBAR_EXP_CC", /*130-134*/ | |
| 1643 "UPCA_CC", "UPCE_CC", "DBAR_STK_CC", "DBAR_OMNSTK_CC", "DBAR_EXPSTK_CC", /*135-139*/ | |
| 1644 "CHANNEL", "CODEONE", "GRIDMATRIX", "UPNQR", "ULTRA", /*140-144*/ | |
| 1645 "RMQR", "BC412", "DXFILMEDGE", /*145-147*/ | |
| 1646 }; | |
| 1647 | |
| 1648 name[0] = '\0'; | |
| 1649 | |
| 1650 if (!ZBarcode_ValidID(symbol_id)) { | |
| 1651 return 1; | |
| 1652 } | |
| 1653 assert(symbol_id >= 0 && symbol_id < ARRAY_SIZE(names) && names[symbol_id][0]); | |
| 1654 | |
| 1655 memcpy(name, "BARCODE_", 8); | |
| 1656 strcpy(name + 8, names[symbol_id]); | |
| 1657 | |
| 1658 return 0; | |
| 1659 } | |
| 1660 | |
| 1661 /* Return the capability flags for symbology `symbol_id` that match `cap_flag` */ | |
| 1662 unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { | |
| 1663 unsigned int result = 0; | |
| 1664 | |
| 1665 if (!ZBarcode_ValidID(symbol_id)) { | |
| 1666 return 0; | |
| 1667 } | |
| 1668 | |
| 1669 if ((cap_flag & ZINT_CAP_HRT) && has_hrt(symbol_id)) { | |
| 1670 result |= ZINT_CAP_HRT; | |
| 1671 } | |
| 1672 if ((cap_flag & ZINT_CAP_STACKABLE) && is_stackable(symbol_id)) { | |
| 1673 result |= ZINT_CAP_STACKABLE; | |
| 1674 } | |
| 1675 if ((cap_flag & ZINT_CAP_EANUPC) && is_upcean(symbol_id)) { | |
| 1676 result |= ZINT_CAP_EANUPC; | |
| 1677 } | |
| 1678 if ((cap_flag & ZINT_CAP_COMPOSITE) && is_composite(symbol_id)) { | |
| 1679 result |= ZINT_CAP_COMPOSITE; | |
| 1680 } | |
| 1681 if ((cap_flag & ZINT_CAP_ECI) && supports_eci(symbol_id)) { | |
| 1682 result |= ZINT_CAP_ECI; | |
| 1683 } | |
| 1684 if ((cap_flag & ZINT_CAP_GS1) && gs1_compliant(symbol_id)) { | |
| 1685 result |= ZINT_CAP_GS1; | |
| 1686 } | |
| 1687 if ((cap_flag & ZINT_CAP_DOTTY) && is_dotty(symbol_id)) { | |
| 1688 result |= ZINT_CAP_DOTTY; | |
| 1689 } | |
| 1690 if (cap_flag & ZINT_CAP_QUIET_ZONES) { | |
| 1691 switch (symbol_id) { /* See `out_quiet_zones()` in "output.c" */ | |
| 1692 case BARCODE_CODE16K: | |
| 1693 case BARCODE_CODE49: | |
| 1694 case BARCODE_CODABLOCKF: | |
| 1695 case BARCODE_HIBC_BLOCKF: | |
| 1696 case BARCODE_ITF14: | |
| 1697 case BARCODE_EANX: | |
| 1698 case BARCODE_EANX_CHK: | |
| 1699 case BARCODE_EANX_CC: | |
| 1700 case BARCODE_ISBNX: | |
| 1701 case BARCODE_UPCA: | |
| 1702 case BARCODE_UPCA_CHK: | |
| 1703 case BARCODE_UPCA_CC: | |
| 1704 case BARCODE_UPCE: | |
| 1705 case BARCODE_UPCE_CHK: | |
| 1706 case BARCODE_UPCE_CC: | |
| 1707 result |= ZINT_CAP_QUIET_ZONES; | |
| 1708 break; | |
| 1709 } | |
| 1710 } | |
| 1711 if ((cap_flag & ZINT_CAP_FIXED_RATIO) && is_fixed_ratio(symbol_id)) { | |
| 1712 result |= ZINT_CAP_FIXED_RATIO; | |
| 1713 } | |
| 1714 if (cap_flag & ZINT_CAP_READER_INIT) { | |
| 1715 /* Note does not include HIBC versions */ | |
| 1716 switch (symbol_id) { | |
| 1717 case BARCODE_CODE128: /* Note does not include GS1_128 or NVE18 */ | |
| 1718 case BARCODE_CODE128AB: | |
| 1719 case BARCODE_CODE16K: | |
| 1720 case BARCODE_CODABLOCKF: | |
| 1721 case BARCODE_PDF417: | |
| 1722 case BARCODE_PDF417COMP: | |
| 1723 case BARCODE_DATAMATRIX: | |
| 1724 case BARCODE_MICROPDF417: | |
| 1725 case BARCODE_AZTEC: | |
| 1726 case BARCODE_DOTCODE: | |
| 1727 case BARCODE_GRIDMATRIX: | |
| 1728 case BARCODE_ULTRA: | |
| 1729 result |= ZINT_CAP_READER_INIT; | |
| 1730 break; | |
| 1731 } | |
| 1732 } | |
| 1733 if (cap_flag & ZINT_CAP_FULL_MULTIBYTE) { | |
| 1734 switch (symbol_id) { | |
| 1735 case BARCODE_QRCODE: | |
| 1736 case BARCODE_MICROQR: | |
| 1737 /* case BARCODE_HIBC_QR: Note character set restricted to ASCII subset */ | |
| 1738 /* case BARCODE_UPNQR: Note does not use Kanji mode */ | |
| 1739 case BARCODE_RMQR: | |
| 1740 case BARCODE_HANXIN: | |
| 1741 case BARCODE_GRIDMATRIX: | |
| 1742 result |= ZINT_CAP_FULL_MULTIBYTE; | |
| 1743 break; | |
| 1744 } | |
| 1745 } | |
| 1746 if (cap_flag & ZINT_CAP_MASK) { | |
| 1747 switch (symbol_id) { | |
| 1748 case BARCODE_QRCODE: | |
| 1749 case BARCODE_MICROQR: | |
| 1750 case BARCODE_UPNQR: | |
| 1751 case BARCODE_HANXIN: | |
| 1752 case BARCODE_DOTCODE: | |
| 1753 result |= ZINT_CAP_MASK; | |
| 1754 break; | |
| 1755 } | |
| 1756 } | |
| 1757 if (cap_flag & ZINT_CAP_STRUCTAPP) { | |
| 1758 switch (symbol_id) { | |
| 1759 case BARCODE_PDF417: | |
| 1760 case BARCODE_PDF417COMP: | |
| 1761 case BARCODE_MAXICODE: | |
| 1762 case BARCODE_QRCODE: /* Note does not include MICROQR, UPNQR or rMQR */ | |
| 1763 case BARCODE_DATAMATRIX: | |
| 1764 case BARCODE_MICROPDF417: | |
| 1765 case BARCODE_AZTEC: | |
| 1766 case BARCODE_HIBC_DM: | |
| 1767 case BARCODE_HIBC_QR: | |
| 1768 case BARCODE_HIBC_PDF: | |
| 1769 case BARCODE_HIBC_MICPDF: | |
| 1770 case BARCODE_HIBC_AZTEC: | |
| 1771 case BARCODE_DOTCODE: | |
| 1772 case BARCODE_CODEONE: | |
| 1773 case BARCODE_GRIDMATRIX: | |
| 1774 case BARCODE_ULTRA: | |
| 1775 result |= ZINT_CAP_STRUCTAPP; | |
| 1776 break; | |
| 1777 } | |
| 1778 } | |
| 1779 if ((cap_flag & ZINT_CAP_COMPLIANT_HEIGHT) && !is_fixed_ratio(symbol_id)) { | |
| 1780 switch (symbol_id) { | |
| 1781 /* These don't have a compliant height defined */ | |
| 1782 case BARCODE_CODE11: /* TODO: Find doc */ | |
| 1783 case BARCODE_C25STANDARD: /* For C25 only have doc for C25INTER */ | |
| 1784 case BARCODE_C25IATA: | |
| 1785 case BARCODE_C25LOGIC: | |
| 1786 case BARCODE_C25IND: | |
| 1787 case BARCODE_CODE128: /* Left to application */ | |
| 1788 case BARCODE_CODE128AB: | |
| 1789 case BARCODE_DPLEIT: /* TODO: Find doc */ | |
| 1790 case BARCODE_DPIDENT: /* TODO: Find doc */ | |
| 1791 case BARCODE_FLAT: /* TODO: Find doc */ | |
| 1792 case BARCODE_MSI_PLESSEY: /* TODO: Find doc */ | |
| 1793 case BARCODE_PDF417: /* Has compliant height but already warns & uses for default */ | |
| 1794 case BARCODE_PDF417COMP: | |
| 1795 case BARCODE_VIN: /* Spec unlikely */ | |
| 1796 case BARCODE_KOREAPOST: /* TODO: Find doc */ | |
| 1797 case BARCODE_MICROPDF417: /* See PDF417 */ | |
| 1798 case BARCODE_PLESSEY: /* TODO: Find doc */ | |
| 1799 case BARCODE_DAFT: /* Generic */ | |
| 1800 case BARCODE_HIBC_128: /* See CODE128 */ | |
| 1801 case BARCODE_HIBC_PDF: /* See PDF417 */ | |
| 1802 case BARCODE_HIBC_MICPDF: /* See PDF417 */ | |
| 1803 break; | |
| 1804 default: | |
| 1805 result |= ZINT_CAP_COMPLIANT_HEIGHT; | |
| 1806 break; | |
| 1807 } | |
| 1808 } | |
| 1809 | |
| 1810 return result; | |
| 1811 } | |
| 1812 | |
| 1813 /* Return default X-dimension in mm for symbology `symbol_id`. Returns 0 on error (invalid `symbol_id`) */ | |
| 1814 float ZBarcode_Default_Xdim(int symbol_id) { | |
| 1815 float x_dim_mm; | |
| 1816 | |
| 1817 if (!ZBarcode_ValidID(symbol_id)) { | |
| 1818 return 0.0f; | |
| 1819 } | |
| 1820 switch (symbol_id) { | |
| 1821 /* Postal 2/4-track */ | |
| 1822 case BARCODE_AUSPOST: | |
| 1823 case BARCODE_AUSREPLY: | |
| 1824 case BARCODE_AUSROUTE: | |
| 1825 case BARCODE_AUSREDIRECT: | |
| 1826 /* Australia Post Customer Barcoding Technical Specifications, average of 0.4 to 0.6 mm */ | |
| 1827 x_dim_mm = 0.5f; | |
| 1828 break; | |
| 1829 case BARCODE_CEPNET: | |
| 1830 case BARCODE_POSTNET: | |
| 1831 case BARCODE_PLANET: | |
| 1832 case BARCODE_USPS_IMAIL: | |
| 1833 /* USPS-B-3200 Section 2.3.1, height 0.145" (average of 0.125, 0.165) / 6.235 (Zint height), same as | |
| 1834 USPS DMM 300 Section 708.4.2.5 using bar pitch (1" / 43) ~ 0.023" */ | |
| 1835 x_dim_mm = 0.591f; | |
| 1836 break; | |
| 1837 case BARCODE_RM4SCC: | |
| 1838 case BARCODE_KIX: | |
| 1839 case BARCODE_MAILMARK_4S: | |
| 1840 /* Royal Mail Mailmark Barcode Definition Document, height 5.1mm / 8 (Zint height) == 0.6375 */ | |
| 1841 x_dim_mm = 0.638f; /* Seems better fit to round up to 3 d.p. */ | |
| 1842 break; | |
| 1843 case BARCODE_JAPANPOST: | |
| 1844 x_dim_mm = 0.6f; /* Japan Post Zip/Barcode Manual */ | |
| 1845 break; | |
| 1846 | |
| 1847 /* GS1 (excluding GS1-128, ITF-14, GS1 QRCODE & GS1 DATAMATRIX - see default) */ | |
| 1848 case BARCODE_EANX: | |
| 1849 case BARCODE_EANX_CHK: | |
| 1850 case BARCODE_EANX_CC: | |
| 1851 case BARCODE_ISBNX: | |
| 1852 case BARCODE_UPCA: | |
| 1853 case BARCODE_UPCA_CHK: | |
| 1854 case BARCODE_UPCA_CC: | |
| 1855 case BARCODE_UPCE: | |
| 1856 case BARCODE_UPCE_CHK: | |
| 1857 case BARCODE_UPCE_CC: | |
| 1858 case BARCODE_DBAR_OMN: | |
| 1859 case BARCODE_DBAR_OMN_CC: | |
| 1860 case BARCODE_DBAR_LTD: | |
| 1861 case BARCODE_DBAR_LTD_CC: | |
| 1862 case BARCODE_DBAR_EXP: | |
| 1863 case BARCODE_DBAR_EXP_CC: | |
| 1864 case BARCODE_DBAR_STK: | |
| 1865 case BARCODE_DBAR_STK_CC: | |
| 1866 case BARCODE_DBAR_OMNSTK: | |
| 1867 case BARCODE_DBAR_OMNSTK_CC: | |
| 1868 case BARCODE_DBAR_EXPSTK: | |
| 1869 case BARCODE_DBAR_EXPSTK_CC: | |
| 1870 x_dim_mm = 0.33f; /* GS1 General Standards 22.0 Section 5.12.3 Table 1 except DBAR_LTD Table 4 */ | |
| 1871 break; | |
| 1872 case BARCODE_DXFILMEDGE: | |
| 1873 /* Measured on Kodak 35mm film, a DX Film Edge with frame number with 31 symbols is 12,51 mm long */ | |
| 1874 x_dim_mm = 0.403548f; | |
| 1875 break; | |
| 1876 /* Specific */ | |
| 1877 case BARCODE_BC412: | |
| 1878 x_dim_mm = 0.12f; /* SEMI T1-95 Table 1 */ | |
| 1879 break; | |
| 1880 case BARCODE_CODABAR: | |
| 1881 x_dim_mm = 0.38f; /* EN 798:1996 Appendix D.1 (d), average of 0.33 to 0.43 mm */ | |
| 1882 break; | |
| 1883 case BARCODE_CODE32: | |
| 1884 x_dim_mm = 0.25f; /* Allegato A Caratteristiche tecniche del bollino farmaceutico, 0.25mm */ | |
| 1885 break; | |
| 1886 case BARCODE_DPD: | |
| 1887 x_dim_mm = 0.375f; /* DPD Parcel Label Specification Version 2.4.1 (19.01.2021) Section 4.6.1.2 */ | |
| 1888 break; | |
| 1889 case BARCODE_FIM: | |
| 1890 /* USPS DMM 300 Section 708.9.3, 0.03125" */ | |
| 1891 x_dim_mm = 0.79375f; | |
| 1892 break; | |
| 1893 case BARCODE_LOGMARS: | |
| 1894 x_dim_mm = 0.34925f; /* MIL-STD-1189 Rev. B Section 5.2, average of 0.0075" and 0.02" */ | |
| 1895 break; | |
| 1896 case BARCODE_MAILMARK_2D: | |
| 1897 /* Royal Mail Mailmark Barcode Definition Document, Section 2.4 */ | |
| 1898 x_dim_mm = 0.5f; | |
| 1899 break; | |
| 1900 case BARCODE_MAXICODE: | |
| 1901 /* ISO/IEC 16023:2000 Table 7, based on L = 25.5mm */ | |
| 1902 x_dim_mm = 0.88f; | |
| 1903 break; | |
| 1904 case BARCODE_PHARMA: | |
| 1905 x_dim_mm = 0.5f; /* Laetus Pharmacode Guide Section 1.2, standard 0.5mm */ | |
| 1906 break; | |
| 1907 case BARCODE_PHARMA_TWO: | |
| 1908 x_dim_mm = 1.0f; /* Laetus Pharmacode Guide Section 1.4, standard 1mm */ | |
| 1909 break; | |
| 1910 case BARCODE_PZN: | |
| 1911 x_dim_mm = 0.25f; /* Technical Information regarding PZN, "normal" X 0.25mm */ | |
| 1912 break; | |
| 1913 case BARCODE_TELEPEN: | |
| 1914 case BARCODE_TELEPEN_NUM: | |
| 1915 /* Telepen Barcode Symbology information and History, average of between 0.010" and 0.0125" */ | |
| 1916 x_dim_mm = 0.28575f; | |
| 1917 break; | |
| 1918 case BARCODE_UPU_S10: | |
| 1919 x_dim_mm = 0.42f; /* Universal Postal Union S10 Section 8, average of 0.33mm & 0.51mm */ | |
| 1920 break; | |
| 1921 | |
| 1922 /* Stacked (excluding GS1 DataBar) */ | |
| 1923 case BARCODE_CODE16K: /* Application-defined */ | |
| 1924 case BARCODE_CODE49: /* ANSI/AIM BC6-2000 Appendix D.2.4, C grade if > 0.25mm */ | |
| 1925 case BARCODE_CODABLOCKF: /* Application-defined */ | |
| 1926 case BARCODE_HIBC_BLOCKF: | |
| 1927 case BARCODE_PDF417: /* Maybe 0.27mm following ISO/IEC 15438:2015 Annex S.2.2 example? */ | |
| 1928 case BARCODE_PDF417COMP: | |
| 1929 case BARCODE_HIBC_PDF: | |
| 1930 case BARCODE_MICROPDF417: | |
| 1931 case BARCODE_HIBC_MICPDF: | |
| 1932 /* Fairly arbitrarily using ISO/IEC 15416:2016 Section 5.3.1 Table 1, aperature diameters 0.125 & 0.250 | |
| 1933 (also fits in 0.25 <= X < 0.5 range for aperature 0.2 from ISO/IEC 15415:2011 Annex D Table D.1) */ | |
| 1934 x_dim_mm = 0.33f; | |
| 1935 break; | |
| 1936 | |
| 1937 /* Application defined (and hence pretty arbitrary) */ | |
| 1938 default: | |
| 1939 if (is_fixed_ratio(symbol_id)) { | |
| 1940 /* GS1 General Standards 22.0 Section 5.12.3 Table 1 (general retail) */ | |
| 1941 x_dim_mm = 0.625f; | |
| 1942 } else { | |
| 1943 /* GS1 General Standards 22.0 Section 5.12.3.4 GS1-128 Tables 2, 4, 5, 6, 8 */ | |
| 1944 x_dim_mm = 0.495f; | |
| 1945 } | |
| 1946 break; | |
| 1947 } | |
| 1948 | |
| 1949 return x_dim_mm; | |
| 1950 } | |
| 1951 | |
| 1952 /* Return the scale to use for `symbol_id` for non-zero X-dimension `x_dim_mm` at `dpmm` dots per mm for | |
| 1953 `filetype`. If `dpmm` zero defaults to 12. If `filetype` NULL/empty, defaults to "GIF". Returns 0 on error */ | |
| 1954 float ZBarcode_Scale_From_XdimDp(int symbol_id, float x_dim_mm, float dpmm, const char *filetype) { | |
| 1955 int i; | |
| 1956 float scale; | |
| 1957 | |
| 1958 if (!ZBarcode_ValidID(symbol_id)) { | |
| 1959 return 0.0f; | |
| 1960 } | |
| 1961 if (x_dim_mm <= 0.0f || x_dim_mm > 10.0f) { /* 10mm == 0.39" */ | |
| 1962 return 0.0f; | |
| 1963 } | |
| 1964 if (dpmm == 0.0f) { | |
| 1965 dpmm = 12.0f; /* ~300 dpi */ | |
| 1966 } else if (dpmm < 0.0f || dpmm > 1000.0f) { /* 1000 dpmm == 25400 dpi */ | |
| 1967 return 0.0f; | |
| 1968 } | |
| 1969 if (filetype && *filetype) { | |
| 1970 if ((i = filetype_idx(filetype)) < 0 || filetypes[i].filetype == 0) { /* Not found or TXT */ | |
| 1971 return 0.0f; | |
| 1972 } | |
| 1973 } else { | |
| 1974 i = filetype_idx("GIF"); /* Default to raster */ | |
| 1975 } | |
| 1976 | |
| 1977 scale = stripf(stripf(x_dim_mm) * stripf(dpmm)); | |
| 1978 | |
| 1979 if (symbol_id == BARCODE_MAXICODE) { | |
| 1980 if (filetypes[i].is_raster) { | |
| 1981 scale /= 10.0f; | |
| 1982 } else if (filetypes[i].filetype == OUT_EMF_FILE) { | |
| 1983 scale /= 40.0f; | |
| 1984 } else { | |
| 1985 scale /= 2.0f; | |
| 1986 } | |
| 1987 } else { | |
| 1988 if (filetypes[i].is_raster) { | |
| 1989 scale = roundf(scale) / 2.0f; /* Half-integer increments */ | |
| 1990 } else { | |
| 1991 scale /= 2.0f; | |
| 1992 } | |
| 1993 } | |
| 1994 scale = stripf(scale); | |
| 1995 | |
| 1996 if (scale > 200.0f) { | |
| 1997 scale = 200.0f; | |
| 1998 } else { | |
| 1999 if (filetypes[i].is_raster) { | |
| 2000 if (symbol_id == BARCODE_MAXICODE) { | |
| 2001 if (scale < 0.2f) { | |
| 2002 scale = 0.2f; | |
| 2003 } | |
| 2004 } else if (scale < 0.5f) { | |
| 2005 scale = 0.5f; /* Note if dotty mode needs further bounding to 1.0 */ | |
| 2006 } | |
| 2007 } else { | |
| 2008 if (scale < 0.1f) { | |
| 2009 scale = 0.1f; | |
| 2010 } | |
| 2011 } | |
| 2012 } | |
| 2013 | |
| 2014 return scale; | |
| 2015 } | |
| 2016 | |
| 2017 /* Reverse of `ZBarcode_Scale_From_XdimDp()` above to estimate the X-dimension or dpmm given non-zero `scale` and | |
| 2018 non-zero `x_dim_mm_or_dpmm`. Return value bound to dpmm max not X-dimension max. Returns 0 on error */ | |
| 2019 float ZBarcode_XdimDp_From_Scale(int symbol_id, float scale, float xdim_mm_or_dpmm, const char *filetype) { | |
| 2020 int i; | |
| 2021 | |
| 2022 if (!ZBarcode_ValidID(symbol_id)) { | |
| 2023 return 0.0f; | |
| 2024 } | |
| 2025 if (scale <= 0.0f || scale > 200.0f) { | |
| 2026 return 0.0f; | |
| 2027 } | |
| 2028 if (xdim_mm_or_dpmm <= 0.0f || xdim_mm_or_dpmm > 1000.0f) { /* 1000 dpmm == 25400 dpi */ | |
| 2029 return 0.0f; | |
| 2030 } | |
| 2031 if (filetype && *filetype) { | |
| 2032 if ((i = filetype_idx(filetype)) < 0 || filetypes[i].filetype == 0) { /* Not found or TXT */ | |
| 2033 return 0.0f; | |
| 2034 } | |
| 2035 } else { | |
| 2036 i = filetype_idx("GIF"); /* Default to raster */ | |
| 2037 } | |
| 2038 | |
| 2039 if (symbol_id == BARCODE_MAXICODE) { | |
| 2040 if (filetypes[i].is_raster) { | |
| 2041 scale *= 10.0f; | |
| 2042 } else if (filetypes[i].filetype == OUT_EMF_FILE) { | |
| 2043 scale *= 40.0f; | |
| 2044 } else { | |
| 2045 scale *= 2.0f; | |
| 2046 } | |
| 2047 } else { | |
| 2048 scale *= 2.0f; | |
| 2049 } | |
| 2050 | |
| 2051 xdim_mm_or_dpmm = stripf(stripf(scale) / stripf(xdim_mm_or_dpmm)); | |
| 2052 | |
| 2053 if (xdim_mm_or_dpmm > 1000.0f) { /* Note if X-dimension sought needs to be further bound to <= 10 on return */ | |
| 2054 xdim_mm_or_dpmm = 1000.0f; | |
| 2055 } | |
| 2056 | |
| 2057 return xdim_mm_or_dpmm; | |
| 2058 } | |
| 2059 | |
| 2060 /* Whether Zint built without PNG support */ | |
| 2061 int ZBarcode_NoPng(void) { | |
| 2062 #ifdef ZINT_NO_PNG | |
| 2063 return 1; | |
| 2064 #else | |
| 2065 return 0; | |
| 2066 #endif | |
| 2067 } | |
| 2068 | |
| 2069 /* Return the version of Zint linked to */ | |
| 2070 int ZBarcode_Version(void) { | |
| 2071 #if ZINT_VERSION_BUILD | |
| 2072 return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE * 10 + ZINT_VERSION_BUILD; | |
| 2073 #else | |
| 2074 return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE; | |
| 2075 #endif | |
| 2076 } | |
| 2077 | |
| 2078 /* vim: set ts=4 sw=4 et : */ |
