Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save brozkeff/b8a5b2b27bf236f1399e197899a4780c to your computer and use it in GitHub Desktop.
Save brozkeff/b8a5b2b27bf236f1399e197899a4780c to your computer and use it in GitHub Desktop.
Attempt to re-insert code to Zint 2.11 from Zint 2.6.7 supporting old code needed for gLabels3 compatibility
From da94d696fac2c4e2eedc6c82e71bd867b5bce177 Mon Sep 17 00:00:00 2001
From: brozkeff <brozkeff@gmail.com>
Date: Fri, 25 Nov 2022 21:03:49 +0100
Subject: [PATCH] Squashed history
---
CMakeLists.txt | 75 ++
library.c | 1874 ++++++++++++++++++++++++++++++++++++++++++++++++
render.c | 859 ++++++++++++++++++++++
zint.h | 454 ++++++++++++
4 files changed, 3262 insertions(+)
create mode 100644 CMakeLists.txt
create mode 100644 library.c
create mode 100755 render.c
create mode 100644 zint.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..2d2fa56
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,75 @@
+# Copyright (C) 2008 by BogDan Vatra < bogdan@licentia.eu >
+# Copyright (C) 2009-2022 Robin Stuart <rstuart114@gmail.com>
+# vim: set ts=4 sw=4 et :
+# re-added render.c to zint_COMMON_SRCS from 2.6.7 for gLabels, by brozkeff 2022-11-25
+
+project(zint)
+
+configure_file(zintconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/zintconfig.h)
+
+set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c general_field.c)
+set(zint_ONEDIM_SRCS bc412.c code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
+set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c)
+set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c)
+set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c output.c)
+set(zint_SRCS ${zint_OUTPUT_SRCS} ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS})
+
+add_library(zint SHARED ${zint_SRCS})
+
+if(WIN32)
+ target_sources(${PROJECT_NAME} PRIVATE libzint.rc)
+endif()
+
+if(ZINT_STATIC)
+ add_library(zint-static STATIC ${zint_SRCS})
+endif()
+
+function(zint_target_link_libraries library)
+ target_link_libraries(zint ${library})
+ if(ZINT_STATIC)
+ target_link_libraries(zint-static ${library})
+ endif()
+endfunction()
+
+function(zint_target_compile_definitions scope definition)
+ target_compile_definitions(zint ${scope} ${definition})
+ if(ZINT_STATIC)
+ target_compile_definitions(zint-static ${scope} ${definition})
+ endif()
+endfunction()
+
+set_target_properties(zint PROPERTIES SOVERSION "${ZINT_VERSION_MAJOR}.${ZINT_VERSION_MINOR}"
+ VERSION ${ZINT_VERSION})
+
+if(ZINT_USE_PNG)
+ find_package(PNG)
+endif()
+
+if(ZINT_USE_PNG AND PNG_FOUND)
+ zint_target_link_libraries(PNG::PNG)
+else()
+ zint_target_compile_definitions(PUBLIC NO_PNG)
+endif()
+
+if(ZINT_TEST)
+ zint_target_compile_definitions(PUBLIC ZINT_TEST)
+endif()
+
+if(NOT MSVC)
+ # Link with standard C math library.
+ zint_target_link_libraries(m)
+endif()
+
+if(MSVC)
+ target_compile_definitions(zint PRIVATE DLL_EXPORT)
+endif()
+
+install(TARGETS zint ${INSTALL_TARGETS_DEFAULT_ARGS})
+if(ZINT_STATIC)
+ install(TARGETS zint-static ${INSTALL_TARGETS_DEFAULT_ARGS})
+endif()
+install(FILES zint.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)
+
+if(ZINT_TEST)
+ add_subdirectory(tests)
+endif()
diff --git a/library.c b/library.c
new file mode 100644
index 0000000..f4e787b
--- /dev/null
+++ b/library.c
@@ -0,0 +1,1874 @@
+/* library.c - external functions of libzint */
+/*
+ libzint - the open source barcode library
+ Copyright (C) 2009-2022 Robin Stuart <rstuart114@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the project nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ */
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include "common.h"
+#include "eci.h"
+#include "gs1.h"
+#include "zfiletypes.h"
+
+/* It's assumed that int is at least 32 bits, the following will compile-time fail if not
+ * https://stackoverflow.com/a/1980056 */
+typedef char static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1];
+
+typedef char static_assert_uint16_is_16bits[sizeof(uint16_t) != 2 ? -1 : 1];
+typedef char static_assert_int32_is_32bits[sizeof(int32_t) != 4 ? -1 : 1];
+typedef char static_assert_uint32_is_32bits[sizeof(uint32_t) != 4 ? -1 : 1];
+typedef char static_assert_uint64_at_least_64bits[sizeof(uint64_t) < 8 ? -1 : 1];
+
+/* Create and initialize a symbol structure */
+struct zint_symbol *ZBarcode_Create(void) {
+ struct zint_symbol *symbol;
+
+ symbol = (struct zint_symbol *) calloc(1, sizeof(*symbol));
+ if (!symbol) return NULL;
+
+ symbol->symbology = BARCODE_CODE128;
+ symbol->scale = 1.0f;
+ strcpy(symbol->fgcolour, "000000");
+ symbol->fgcolor = &symbol->fgcolour[0];
+ strcpy(symbol->bgcolour, "ffffff");
+ symbol->bgcolor = &symbol->bgcolour[0];
+#ifdef NO_PNG
+ strcpy(symbol->outfile, "out.gif");
+#else
+ strcpy(symbol->outfile, "out.png");
+#endif
+ symbol->option_1 = -1;
+ symbol->show_hrt = 1; /* Show human readable text */
+ symbol->fontsize = 8;
+ symbol->input_mode = DATA_MODE;
+ symbol->eci = 0; /* Default 0 uses ECI 3 */
+ symbol->dot_size = 4.0f / 5.0f;
+ symbol->guard_descent = 5.0f;
+ symbol->warn_level = WARN_DEFAULT;
+ symbol->bitmap = NULL;
+ symbol->alphamap = NULL;
+ symbol->vector = NULL;
+
+ return symbol;
+}
+
+INTERNAL void vector_free(struct zint_symbol *symbol); /* Free vector structures */
+
+/* Free any output buffers that may have been created and initialize output fields */
+void ZBarcode_Clear(struct zint_symbol *symbol) {
+ int i;
+
+ if (!symbol) return;
+
+ for (i = 0; i < symbol->rows; i++) {
+ memset(symbol->encoded_data[i], 0, sizeof(symbol->encoded_data[0]));
+ }
+ symbol->rows = 0;
+ symbol->width = 0;
+ memset(symbol->row_height, 0, sizeof(symbol->row_height));
+ memset(symbol->text, 0, sizeof(symbol->text));
+ symbol->errtxt[0] = '\0';
+ if (symbol->bitmap != NULL) {
+ free(symbol->bitmap);
+ symbol->bitmap = NULL;
+ }
+ if (symbol->alphamap != NULL) {
+ free(symbol->alphamap);
+ symbol->alphamap = NULL;
+ }
+ symbol->bitmap_width = 0;
+ symbol->bitmap_height = 0;
+ symbol->bitmap_byte_length = 0;
+
+ /* If there is a rendered version, ensure its memory is released */
+ vector_free(symbol);
+}
+
+/* Free a symbol structure, including any output buffers */
+void ZBarcode_Delete(struct zint_symbol *symbol) {
+ if (!symbol) return;
+
+ if (symbol->bitmap != NULL)
+ free(symbol->bitmap);
+ if (symbol->alphamap != NULL)
+ free(symbol->alphamap);
+
+ /* If there is a rendered version, ensure its memory is released */
+ vector_free(symbol);
+
+ free(symbol);
+}
+
+/* Symbology handlers */
+INTERNAL int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */
+INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 3 from 9 (or Code 39) */
+INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */
+/* Extended Code 3 from 9 (or Code 39+) */
+INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length);
+/* Codabar - a simple substitution cipher */
+INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length);
+/* Code 2 of 5 Standard (& Matrix) */
+INTERNAL int c25standard(struct zint_symbol *symbol, unsigned char source[], int length);
+INTERNAL int c25ind(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Industrial */
+INTERNAL int c25iata(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 IATA */
+INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Interleaved */
+INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Data Logic */
+INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length); /* ITF-14 */
+INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */
+INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */
+/* Code 93 - a re-working of Code 39+, generates 2 check digits */
+INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int length);
+INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 128 and NVE-18 */
+INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-128 (GS1-128) */
+INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */
+INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */
+INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen ASCII */
+INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen Numeric */
+INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* Plessey Code */
+INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode One Track */
+INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length); /* Flattermarken */
+INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length); /* Facing Identification Mark */
+INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode Two Track */
+INTERNAL int postnet(struct zint_symbol *symbol, unsigned char source[], int length); /* Postnet */
+INTERNAL int planet(struct zint_symbol *symbol, unsigned char source[], int length); /* PLANET */
+/* Intelligent Mail (aka USPS OneCode) */
+INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int length);
+INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */
+INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */
+INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */
+INTERNAL int pdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* PDF417 */
+INTERNAL int micropdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Micro PDF417 */
+INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Maxicode */
+INTERNAL int dbar_omn(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Omnidirectional */
+INTERNAL int dbar_ltd(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Limited */
+INTERNAL int dbar_exp(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Expanded */
+INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */
+INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length); /* TNT KIX Code */
+INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Aztec Code */
+INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length); /* Italian Pharmacode */
+INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length); /* DAFT Code */
+INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-14 */
+INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length); /* NVE-18 */
+INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length); /* Micro QR Code */
+INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */
+INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */
+INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */
+INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 49 */
+INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */
+INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Code One */
+INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Grid Matrix */
+INTERNAL int hanxin(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Han Xin */
+INTERNAL int dotcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* DotCode */
+INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int length); /* Codablock */
+INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length); /* UPNQR */
+INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* QR Code */
+/* Data Matrix (IEC16022) */
+INTERNAL int datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count);
+/* VIN Code (Vehicle Identification Number) */
+INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length);
+/* Royal Mail 4-state Mailmark */
+INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int length);
+INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Ultracode */
+INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* rMQR */
+INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length); /* DPD Code */
+INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int length); /* BC412 */
+
+/* Output handlers */
+INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
+INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */
+
+extern int render_plot(struct zint_symbol *symbol, float width, float height); /* Plot to gLabels - backported from 2.6.7 by brozkeff 2022-11-25 */
+
+/* Prefix error message with Error/Warning */
+static int error_tag(struct zint_symbol *symbol, int error_number, const char *error_string) {
+
+ if (error_number != 0) {
+ static const char error_fmt[] = "Error %.93s"; /* Truncate if too long */
+ static const char warn_fmt[] = "Warning %.91s"; /* Truncate if too long */
+ const char *fmt = error_number >= ZINT_ERROR ? error_fmt : warn_fmt;
+ char error_buffer[100];
+
+ if (error_number < ZINT_ERROR && symbol->warn_level == WARN_FAIL_ALL) {
+ /* Convert to error equivalent */
+ if (error_number == ZINT_WARN_NONCOMPLIANT) {
+ error_number = ZINT_ERROR_NONCOMPLIANT;
+ } else if (error_number == ZINT_WARN_USES_ECI) {
+ error_number = ZINT_ERROR_USES_ECI;
+ } else { /* ZINT_WARN_INVALID_OPTION */
+ error_number = ZINT_ERROR_INVALID_OPTION;
+ }
+ fmt = error_fmt;
+ }
+ sprintf(error_buffer, fmt, error_string ? error_string : symbol->errtxt);
+ strcpy(symbol->errtxt, error_buffer);
+ }
+
+ return error_number;
+}
+
+#ifdef ZINT_TEST /* Wrapper for direct testing */
+INTERNAL int error_tag_test(struct zint_symbol *symbol, int error_number, const char *error_string) {
+ return error_tag(symbol, error_number, error_string);
+}
+#endif
+
+/* Output a hexadecimal representation of the rendered symbol */
+static int dump_plot(struct zint_symbol *symbol) {
+ FILE *f;
+ int i, r;
+ char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ int space = 0;
+
+ if (symbol->output_options & BARCODE_STDOUT) {
+ f = stdout;
+ } else {
+ f = fopen(symbol->outfile, "w");
+ if (!f) {
+ strcpy(symbol->errtxt, "201: Could not open output file");
+ return ZINT_ERROR_FILE_ACCESS;
+ }
+ }
+
+ for (r = 0; r < symbol->rows; r++) {
+ int byt = 0;
+ for (i = 0; i < symbol->width; i++) {
+ byt = byt << 1;
+ if (symbol->symbology == BARCODE_ULTRA) {
+ if (module_colour_is_set(symbol, r, i)) {
+ byt += 1;
+ }
+ } else {
+ if (module_is_set(symbol, r, i)) {
+ byt += 1;
+ }
+ }
+ if (((i + 1) % 4) == 0) {
+ fputc(hex[byt], f);
+ space++;
+ byt = 0;
+ }
+ if (space == 2 && i + 1 < symbol->width) {
+ fputc(' ', f);
+ space = 0;
+ }
+ }
+
+ if ((symbol->width % 4) != 0) {
+ byt = byt << (4 - (symbol->width % 4));
+ fputc(hex[byt], f);
+ }
+ fputs("\n", f);
+ space = 0;
+ }
+
+ if (symbol->output_options & BARCODE_STDOUT) {
+ fflush(f);
+ } else {
+ fclose(f);
+ }
+
+ return 0;
+}
+
+/* Permitted HIBC characters */
+static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */
+
+/* Process health industry bar code data */
+static int hibc(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
+ unsigned char *source = segs[0].source;
+ int length = segs[0].length;
+
+ int i;
+ int counter, error_number = 0;
+ char to_process[110 + 2 + 1];
+ int posns[110];
+
+ /* without "+" and check: max 110 characters in HIBC 2.6 */
+ if (length > 110) {
+ strcpy(symbol->errtxt, "202: Data too long for HIBC LIC (110 character maximum)");
+ return ZINT_ERROR_TOO_LONG;
+ }
+ to_upper(source, length);
+ if (!is_sane_lookup(TECHNETIUM, sizeof(TECHNETIUM) - 1, source, length, posns)) {
+ strcpy(symbol->errtxt, "203: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)");
+ return ZINT_ERROR_INVALID_DATA;
+ }
+
+ counter = 41;
+ for (i = 0; i < length; i++) {
+ counter += posns[i];
+ }
+ counter = counter % 43;
+
+ to_process[0] = '+';
+ memcpy(to_process + 1, source, length);
+ to_process[++length] = TECHNETIUM[counter];
+ to_process[++length] = '\0';
+
+ segs[0].source = (unsigned char *) to_process;
+ segs[0].length = length;
+
+ switch (symbol->symbology) {
+ case BARCODE_HIBC_128:
+ error_number = code128(symbol, segs[0].source, segs[0].length);
+ ustrcpy(symbol->text, "*");
+ ustrcat(symbol->text, to_process);
+ ustrcat(symbol->text, "*");
+ break;
+ case BARCODE_HIBC_39:
+ symbol->option_2 = 0;
+ error_number = code39(symbol, segs[0].source, segs[0].length);
+ ustrcpy(symbol->text, "*");
+ ustrcat(symbol->text, to_process);
+ ustrcat(symbol->text, "*");
+ break;
+ case BARCODE_HIBC_DM:
+ error_number = datamatrix(symbol, segs, seg_count);
+ break;
+ case BARCODE_HIBC_QR:
+ error_number = qrcode(symbol, segs, seg_count);
+ break;
+ case BARCODE_HIBC_PDF:
+ error_number = pdf417(symbol, segs, seg_count);
+ break;
+ case BARCODE_HIBC_MICPDF:
+ error_number = micropdf417(symbol, segs, seg_count);
+ break;
+ case BARCODE_HIBC_AZTEC:
+ error_number = aztec(symbol, segs, seg_count);
+ break;
+ case BARCODE_HIBC_BLOCKF:
+ error_number = codablockf(symbol, segs[0].source, segs[0].length);
+ break;
+ }
+
+ return error_number;
+}
+
+/* Returns 1 if symbology MUST have GS1 data */
+static int check_force_gs1(const int symbology) {
+
+ switch (symbology) {
+ case BARCODE_GS1_128:
+ case BARCODE_EAN14:
+ case BARCODE_NVE18:
+ case BARCODE_DBAR_EXP:
+ case BARCODE_DBAR_EXPSTK:
+ return 1;
+ break;
+ }
+
+ return is_composite(symbology);
+}
+
+/* Returns 1 if symbology supports GS1 data */
+static int gs1_compliant(const int symbology) {
+
+ switch (symbology) {
+ case BARCODE_CODE16K:
+ case BARCODE_AZTEC:
+ case BARCODE_DATAMATRIX:
+ case BARCODE_CODE49:
+ case BARCODE_QRCODE:
+ case BARCODE_DOTCODE:
+ case BARCODE_CODEONE:
+ case BARCODE_ULTRA:
+ case BARCODE_RMQR:
+ /* TODO: case BARCODE_CODABLOCKF: */
+ /* TODO: case BARCODE_HANXIN: */
+ /* TODO: case BARCODE_GRIDMATRIX: */
+ return 1;
+ break;
+ }
+
+ return check_force_gs1(symbology);
+}
+
+/* Returns 1 if symbology can encode the ECI character */
+static int supports_eci(const int symbology) {
+
+ switch (symbology) {
+ case BARCODE_AZTEC:
+ case BARCODE_DATAMATRIX:
+ case BARCODE_MAXICODE:
+ case BARCODE_MICROPDF417:
+ case BARCODE_PDF417:
+ case BARCODE_PDF417COMP:
+ case BARCODE_QRCODE:
+ case BARCODE_DOTCODE:
+ case BARCODE_CODEONE:
+ case BARCODE_GRIDMATRIX:
+ case BARCODE_HANXIN:
+ case BARCODE_ULTRA:
+ case BARCODE_RMQR:
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns 1 if symbology is Health Industry Bar Code */
+static int is_hibc(const int symbology) {
+
+ switch (symbology) {
+ case BARCODE_HIBC_128:
+ case BARCODE_HIBC_39:
+ case BARCODE_HIBC_DM:
+ case BARCODE_HIBC_QR:
+ case BARCODE_HIBC_PDF:
+ case BARCODE_HIBC_MICPDF:
+ case BARCODE_HIBC_BLOCKF:
+ case BARCODE_HIBC_AZTEC:
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns 1 if symbology supports HRT */
+static int has_hrt(const int symbology) {
+
+ if (is_fixed_ratio(symbology)) {
+ return 0;
+ }
+
+ switch (symbology) { /* These don't support HRT */
+ case BARCODE_CODE16K:
+ case BARCODE_CODE49:
+ case BARCODE_FLAT:
+ case BARCODE_POSTNET:
+ case BARCODE_FIM:
+ case BARCODE_PHARMA:
+ case BARCODE_PHARMA_TWO:
+ case BARCODE_PDF417:
+ case BARCODE_PDF417COMP:
+ case BARCODE_AUSPOST:
+ case BARCODE_AUSREPLY:
+ case BARCODE_AUSROUTE:
+ case BARCODE_AUSREDIRECT:
+ case BARCODE_RM4SCC:
+ case BARCODE_CODABLOCKF:
+ case BARCODE_JAPANPOST:
+ case BARCODE_DBAR_STK:
+ case BARCODE_DBAR_OMNSTK:
+ case BARCODE_DBAR_EXPSTK:
+ case BARCODE_PLANET:
+ case BARCODE_MICROPDF417:
+ case BARCODE_USPS_IMAIL:
+ case BARCODE_KIX:
+ case BARCODE_DAFT:
+ case BARCODE_HIBC_PDF:
+ case BARCODE_HIBC_MICPDF:
+ case BARCODE_HIBC_BLOCKF:
+ case BARCODE_MAILMARK:
+ case BARCODE_DBAR_STK_CC:
+ case BARCODE_DBAR_OMNSTK_CC:
+ case BARCODE_DBAR_EXPSTK_CC:
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+/* Suppress warning ISO C forbids initialization between function pointer and ‘void *’ */
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
+/* Used for dispatching barcodes and for whether symbol id valid */
+typedef int (*barcode_segs_func_t)(struct zint_symbol *, struct zint_seg[], const int);
+typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char[], int);
+static const void *barcode_funcs[BARCODE_LAST + 1] = {
+ NULL, code11, c25standard, c25inter, c25iata, /*0-4*/
+ NULL, c25logic, c25ind, code39, excode39, /*5-9*/
+ NULL, NULL, NULL, eanx, eanx, /*10-14*/
+ NULL, gs1_128, NULL, codabar, NULL, /*15-19*/
+ code128, dpleit, dpident, code16k, code49, /*20-24*/
+ code93, NULL, NULL, flat, dbar_omn, /*25-29*/
+ dbar_ltd, dbar_exp, telepen, NULL, eanx, /*30-34*/
+ eanx, NULL, eanx, eanx, NULL, /*35-39*/
+ postnet, NULL, NULL, NULL, NULL, /*40-44*/
+ NULL, NULL, msi_plessey, NULL, fim, /*45-49*/
+ code39, pharma, pzn, pharma_two, postnet, /*50-54*/
+ pdf417, pdf417, maxicode, qrcode, NULL, /*55-59*/
+ code128, NULL, NULL, auspost, NULL, /*60-64*/
+ NULL, auspost, auspost, auspost, eanx, /*65-69*/
+ rm4scc, datamatrix, ean14, vin, codablockf, /*70-74*/
+ nve18, japanpost, koreapost, NULL, dbar_omn, /*75-79*/
+ dbar_omn, dbar_exp, planet, NULL, micropdf417, /*80-84*/
+ usps_imail, plessey, telepen_num, NULL, itf14, /*85-89*/
+ kix, NULL, aztec, daft, NULL, /*90-94*/
+ NULL, dpd, microqr, hibc, hibc, /*95-99*/
+ NULL, NULL, hibc, NULL, hibc, /*100-104*/
+ NULL, hibc, NULL, hibc, NULL, /*105-109*/
+ hibc, NULL, hibc, NULL, NULL, /*110-114*/
+ dotcode, hanxin, NULL, NULL, NULL, /*115-119*/
+ NULL, mailmark, NULL, NULL, NULL, /*120-124*/
+ NULL, NULL, NULL, azrune, code32, /*125-129*/
+ composite, composite, composite, composite, composite, /*130-134*/
+ composite, composite, composite, composite, composite, /*135-139*/
+ channel, codeone, gridmatrix, upnqr, ultra, /*140-144*/
+ rmqr, bc412,
+};
+
+static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count);
+
+/* Main dispatch, checking for barcodes which handle ECIs/character sets themselves, otherwise calling
+ `reduced_charset()` */
+static int extended_or_reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
+ int error_number = 0;
+
+ switch (symbol->symbology) {
+ /* These are the "elite" standards which have support for specific character sets + ECI */
+ case BARCODE_QRCODE:
+ case BARCODE_GRIDMATRIX:
+ case BARCODE_HANXIN:
+ case BARCODE_RMQR:
+ error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, segs, seg_count);
+ break;
+ /* These are the standards which have support for specific character sets but not ECI */
+ case BARCODE_MICROQR:
+ case BARCODE_UPNQR:
+ error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, segs[0].source,
+ segs[0].length);
+ break;
+ default: error_number = reduced_charset(symbol, segs, seg_count);
+ break;
+ }
+
+ return error_number;
+}
+
+/* These are the "norm" standards which only support Latin-1 at most, though a few support ECI */
+static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
+ int error_number = 0;
+ int i;
+ struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count);
+ int *convertible = (int *) z_alloca(sizeof(int) * seg_count);
+
+ if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible_segs(segs, seg_count, convertible)) {
+ unsigned char *preprocessed;
+ const int eci_length_segs = get_eci_length_segs(segs, seg_count);
+ unsigned char *preprocessed_buf = (unsigned char *) z_alloca(eci_length_segs + seg_count);
+
+ /* Prior check ensures ECI only set for those that support it */
+ segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */
+ preprocessed = preprocessed_buf;
+ for (i = 0; i < seg_count; i++) {
+ if (convertible[i]) {
+ error_number = utf8_to_eci(local_segs[i].eci, local_segs[i].source, preprocessed,
+ &local_segs[i].length);
+ if (error_number != 0) {
+ if (local_segs[i].eci) {
+ sprintf(symbol->errtxt, "244: Invalid character in input data for ECI %d", local_segs[i].eci);
+ } else {
+ strcpy(symbol->errtxt, "204: Invalid character in input data (ISO/IEC 8859-1 only)");
+ }
+ return error_number;
+ }
+ local_segs[i].source = preprocessed;
+ preprocessed += local_segs[i].length + 1;
+ }
+ }
+ if (supports_eci(symbol->symbology) || is_hibc(symbol->symbology)) {
+ error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs, seg_count);
+ } else {
+ error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs[0].source,
+ local_segs[0].length);
+ }
+ } else {
+ if (supports_eci(symbol->symbology) || is_hibc(symbol->symbology)) {
+ segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */
+ error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs, seg_count);
+ } else {
+ error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, segs[0].source,
+ segs[0].length);
+ }
+ }
+
+ return error_number;
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+/* Remove Unicode BOM at start of data */
+static void strip_bom(unsigned char *source, int *input_length) {
+ int i;
+
+ /* Note if BOM is only data then not stripped */
+ if (*input_length > 3 && (source[0] == 0xef) && (source[1] == 0xbb) && (source[2] == 0xbf)) {
+ /* BOM at start of input data, strip in accordance with RFC 3629 */
+ for (i = 3; i <= *input_length; i++) { /* Include terminating NUL */
+ source[i - 3] = source[i];
+ }
+ *input_length -= 3;
+ }
+}
+
+#ifdef ZINT_TEST /* Wrapper for direct testing */
+INTERNAL void strip_bom_test(unsigned char *source, int *input_length) {
+ strip_bom(source, input_length);
+}
+#endif
+
+/* Helper to convert base octal, decimal, hexadecimal escape sequence */
+static int esc_base(struct zint_symbol *symbol, unsigned char *input_string, int length, int in_posn, int base) {
+ int c1, c2, c3;
+ int min_len = base == 'x' ? 2 : 3;
+
+ if (in_posn + min_len > length) {
+ sprintf(symbol->errtxt, "232: Incomplete '\\%c' escape sequence in input data", base);
+ return -1;
+ }
+ c1 = ctoi(input_string[in_posn]);
+ c2 = ctoi(input_string[in_posn + 1]);
+ if (base == 'd') {
+ c3 = ctoi(input_string[in_posn + 2]);
+ if ((c1 >= 0 && c1 <= 9) && (c2 >= 0 && c2 <= 9) && (c3 >= 0 && c3 <= 9)) {
+ return c1 * 100 + c2 * 10 + c3;
+ }
+ } else if (base == 'o') {
+ c3 = ctoi(input_string[in_posn + 2]);
+ if ((c1 >= 0 && c1 <= 7) && (c2 >= 0 && c2 <= 7) && (c3 >= 0 && c3 <= 7)) {
+ return (c1 << 6) | (c2 << 3) | c3;
+ }
+ } else {
+ if ((c1 >= 0) && (c2 >= 0)) {
+ return (c1 << 4) | c2;
+ }
+ }
+
+ sprintf(symbol->errtxt, "233: Invalid character for '\\%c' escape sequence in input data (%s only)",
+ base, base == 'd' ? "decimal" : base == 'o' ? "octal" : "hexadecimal" );
+ return -1;
+}
+
+/* Helper to parse escape sequences */
+static int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string, int *p_length) {
+ const int length = *p_length;
+ int in_posn, out_posn;
+ int ch;
+ int val;
+ int i;
+ unsigned long unicode;
+ unsigned char *escaped_string = (unsigned char *) z_alloca(length + 1);
+
+ in_posn = 0;
+ out_posn = 0;
+
+ do {
+ if (input_string[in_posn] == '\\') {
+ if (in_posn + 1 >= length) {
+ strcpy(symbol->errtxt, "236: Incomplete escape character in input data");
+ return ZINT_ERROR_INVALID_DATA;
+ }
+ ch = input_string[in_posn + 1];
+ /* NOTE: if add escape character, must also update regex in "frontend_qt/datawindow.php" */
+ switch (ch) {
+ case '0': escaped_string[out_posn] = 0x00; /* Null */
+ in_posn += 2;
+ break;
+ case 'E': escaped_string[out_posn] = 0x04; /* End of Transmission */
+ in_posn += 2;
+ break;
+ case 'a': escaped_string[out_posn] = 0x07; /* Bell */
+ in_posn += 2;
+ break;
+ case 'b': escaped_string[out_posn] = 0x08; /* Backspace */
+ in_posn += 2;
+ break;
+ case 't': escaped_string[out_posn] = 0x09; /* Horizontal tab */
+ in_posn += 2;
+ break;
+ case 'n': escaped_string[out_posn] = 0x0a; /* Line feed */
+ in_posn += 2;
+ break;
+ case 'v': escaped_string[out_posn] = 0x0b; /* Vertical tab */
+ in_posn += 2;
+ break;
+ case 'f': escaped_string[out_posn] = 0x0c; /* Form feed */
+ in_posn += 2;
+ break;
+ case 'r': escaped_string[out_posn] = 0x0d; /* Carriage return */
+ in_posn += 2;
+ break;
+ case 'e': escaped_string[out_posn] = 0x1b; /* Escape */
+ in_posn += 2;
+ break;
+ case 'G': escaped_string[out_posn] = 0x1d; /* Group Separator */
+ in_posn += 2;
+ break;
+ case 'R': escaped_string[out_posn] = 0x1e; /* Record Separator */
+ in_posn += 2;
+ break;
+ case 'd':
+ case 'o': /* Undocumented (as not very useful for most people) */
+ case 'x':
+ if ((val = esc_base(symbol, input_string, length, in_posn + 2, ch)) == -1) {
+ return ZINT_ERROR_INVALID_DATA;
+ }
+ escaped_string[out_posn] = val;
+ in_posn += 4 + (ch != 'x');
+ break;
+ case '\\': escaped_string[out_posn] = '\\';
+ in_posn += 2;
+ break;
+ case 'u':
+ case 'U':
+ if (in_posn + 6 > length || (ch == 'U' && in_posn + 8 > length)) {
+ sprintf(symbol->errtxt, "209: Incomplete '\\%c' escape sequence in input data", ch);
+ return ZINT_ERROR_INVALID_DATA;
+ }
+ unicode = 0;
+ for (i = 0; i < 6; i++) {
+ if ((val = ctoi(input_string[in_posn + i + 2])) == -1) {
+ sprintf(symbol->errtxt,
+ "211: Invalid character for '\\%c' escape sequence in input data (hexadecimal only)",
+ ch);
+ return ZINT_ERROR_INVALID_DATA;
+ }
+ unicode = (unicode << 4) | val;
+ if (i == 3 && ch == 'u') {
+ break;
+ }
+ }
+ /* Exclude reversed BOM and surrogates and out-of-range */
+ if (unicode == 0xfffe || (unicode >= 0xd800 && unicode < 0xe000) || unicode > 0x10ffff) {
+ sprintf(symbol->errtxt, "246: Invalid value for '\\%c' escape sequence in input data", ch);
+ return ZINT_ERROR_INVALID_DATA;
+ }
+ if (unicode >= 0x800) {
+ if (unicode >= 0x10000) {
+ escaped_string[out_posn] = 0xf0 + (unsigned char) (unicode >> 16);
+ out_posn++;
+ }
+ escaped_string[out_posn] = 0xe0 + ((unicode & 0xf000) >> 12);
+ out_posn++;
+ escaped_string[out_posn] = 0x80 + ((unicode & 0x0fc0) >> 6);
+ out_posn++;
+ escaped_string[out_posn] = 0x80 + (unicode & 0x003f);
+ } else if (unicode >= 0x80) {
+ escaped_string[out_posn] = 0xc0 + ((unicode & 0x07c0) >> 6);
+ out_posn++;
+ escaped_string[out_posn] = 0x80 + (unicode & 0x003f);
+ } else {
+ escaped_string[out_posn] = unicode & 0x7f;
+ }
+ in_posn += 6 + (ch == 'U') * 2;
+ break;
+ default: sprintf(symbol->errtxt, "234: Unrecognised escape character '\\%c' in input data", ch);
+ return ZINT_ERROR_INVALID_DATA;
+ break;
+ }
+ } else {
+ escaped_string[out_posn] = input_string[in_posn];
+ in_posn++;
+ }
+ out_posn++;
+ } while (in_posn < length);
+
+ memcpy(input_string, escaped_string, out_posn);
+ input_string[out_posn] = '\0';
+ *p_length = out_posn;
+
+ return 0;
+}
+
+#ifdef ZINT_TEST /* Wrapper for direct testing */
+INTERNAL int escape_char_process_test(struct zint_symbol *symbol, unsigned char *input_string, int *length) {
+ return escape_char_process(symbol, input_string, length);
+}
+#endif
+
+/* Encode a barcode. If `length` is 0, `source` must be NUL-terminated. */
+int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length) {
+ struct zint_seg segs[1];
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ segs[0].eci = symbol->eci;
+ segs[0].source = (unsigned char *) source;
+ segs[0].length = length;
+
+ return ZBarcode_Encode_Segs(symbol, segs, 1);
+}
+
+/* Encode a barcode with multiple ECI segments. */
+int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count) {
+ int error_number, warn_number = 0;
+ int total_len = 0;
+ int have_zero_eci = 0;
+ int i;
+ unsigned char *local_source;
+ struct zint_seg *local_segs;
+ unsigned char *local_sources;
+ local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * (seg_count > 0 ? seg_count : 1));
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ if (segs == NULL) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "200: Input segments NULL");
+ }
+ /* `seg_count` zero dealt with via `total_len` zero below */
+ if (seg_count > ZINT_MAX_SEG_COUNT) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "771: Too many input segments (max 256)");
+ }
+
+ if ((symbol->input_mode & 0x07) > 2) {
+ symbol->input_mode = DATA_MODE; /* Reset completely TODO: in future, warn/error */
+ }
+
+ /* Check segment lengths */
+ for (i = 0; i < seg_count; i++) {
+ local_segs[i] = segs[i];
+ if (local_segs[i].source == NULL) {
+ sprintf(symbol->errtxt, "772: Input segment %d source NULL", i);
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL);
+ }
+ if (local_segs[i].length <= 0) {
+ local_segs[i].length = (int) ustrlen(local_segs[i].source);
+ }
+ if (local_segs[i].length <= 0) {
+ if (i == 0) {
+ /* Note: should really be referencing the symbology only after the symbology check switch below */
+ if (is_composite(symbol->symbology) &&
+ ((symbol->input_mode & 0x07) == GS1_MODE || check_force_gs1(symbol->symbology))) {
+ strcpy(symbol->errtxt, "779: No composite data in 2D component");
+ } else {
+ sprintf(symbol->errtxt, "778: No input data%s",
+ supports_eci(symbol->symbology) ? " (segment 0 empty)" : "");
+ }
+ } else {
+ sprintf(symbol->errtxt, "773: Input segment %d empty", i);
+ }
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL);
+ }
+ if (local_segs[i].length > ZINT_MAX_DATA_LEN) {
+ return error_tag(symbol, ZINT_ERROR_TOO_LONG, "777: Input data too long");
+ }
+ total_len += local_segs[i].length;
+ }
+
+ if (total_len == 0) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "205: No input data");
+ }
+
+ if (symbol->debug & ZINT_DEBUG_PRINT) {
+ printf("ZBarcode_Encode_Segs: symbology: %d, input_mode: 0x%X, ECI: %d, option_1: %d, option_2: %d,"
+ " option_3: %d, scale: %g\n output_options: 0x%X, fg: %s, bg: %s,"
+ " seg_count: %d, length[0] %d," " First 10 source[0] \"%.*s\", First 10 primary: \"%.10s\"\n",
+ symbol->symbology, symbol->input_mode, symbol->eci, symbol->option_1, symbol->option_2,
+ symbol->option_3, symbol->scale, symbol->output_options, symbol->fgcolour, symbol->bgcolour,
+ seg_count, local_segs[0].length, local_segs[0].length < 10 ? local_segs[0].length : 10,
+ local_segs[0].source, symbol->primary);
+ }
+
+ if (total_len > ZINT_MAX_DATA_LEN) {
+ return error_tag(symbol, ZINT_ERROR_TOO_LONG, "243: Input data too long");
+ }
+
+ /* Reconcile symbol ECI and first segment ECI if both set */
+ if (symbol->eci != local_segs[0].eci) {
+ if (symbol->eci && local_segs[0].eci) {
+ sprintf(symbol->errtxt, "774: Symbol ECI %d must match segment zero ECI %d", symbol->eci,
+ local_segs[0].eci);
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, NULL);
+ }
+ if (symbol->eci) {
+ local_segs[0].eci = symbol->eci;
+ } else {
+ symbol->eci = local_segs[0].eci;
+ }
+ }
+
+ /* Check the symbology field */
+ if (!ZBarcode_ValidID(symbol->symbology)) {
+ int orig_symbology = symbol->symbology; /* For self-check */
+ if (symbol->symbology < 1) {
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "206: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ /* symbol->symbologys 1 to 126 are defined by tbarcode */
+ } else if (symbol->symbology == 5) {
+ symbol->symbology = BARCODE_C25STANDARD;
+ } else if ((symbol->symbology >= 10) && (symbol->symbology <= 12)) {
+ symbol->symbology = BARCODE_EANX;
+ } else if (symbol->symbology == 15) {
+ symbol->symbology = BARCODE_EANX;
+ } else if (symbol->symbology == 17) {
+ symbol->symbology = BARCODE_UPCA;
+ } else if (symbol->symbology == 19) {
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "207: Codabar 18 not supported");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODABAR;
+ } else if (symbol->symbology == 26) { /* UPC-A up to tbarcode 9, ISSN for tbarcode 10+ */
+ symbol->symbology = BARCODE_UPCA;
+ } else if (symbol->symbology == 27) { /* UPCD1 up to tbarcode 9, ISSN + 2 digit add-on for tbarcode 10+ */
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "208: UPCD1 not supported");
+ } else if (symbol->symbology == 33) {
+ symbol->symbology = BARCODE_GS1_128;
+ } else if (symbol->symbology == 36) {
+ symbol->symbology = BARCODE_UPCA;
+ } else if (symbol->symbology == 39) {
+ symbol->symbology = BARCODE_UPCE;
+ } else if ((symbol->symbology >= 41) && (symbol->symbology <= 45)) {
+ symbol->symbology = BARCODE_POSTNET;
+ } else if (symbol->symbology == 46) {
+ symbol->symbology = BARCODE_PLESSEY;
+ } else if (symbol->symbology == 48) {
+ symbol->symbology = BARCODE_NVE18;
+ } else if ((symbol->symbology == 59) || (symbol->symbology == 61)) {
+ symbol->symbology = BARCODE_CODE128;
+ } else if (symbol->symbology == 62) {
+ symbol->symbology = BARCODE_CODE93;
+ } else if ((symbol->symbology == 64) || (symbol->symbology == 65)) {
+ symbol->symbology = BARCODE_AUSPOST;
+ } else if (symbol->symbology == 78) {
+ symbol->symbology = BARCODE_DBAR_OMN;
+ } else if (symbol->symbology == 83) {
+ symbol->symbology = BARCODE_PLANET;
+ } else if (symbol->symbology == 88) {
+ symbol->symbology = BARCODE_GS1_128;
+ } else if (symbol->symbology == 91) { /* BC412 up to tbarcode 9, Code 32 for tbarcode 10+ */
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "212: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ } else if ((symbol->symbology >= 94) && (symbol->symbology <= 95)) {
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "213: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ } else if (symbol->symbology == 100) {
+ symbol->symbology = BARCODE_HIBC_128;
+ } else if (symbol->symbology == 101) {
+ symbol->symbology = BARCODE_HIBC_39;
+ } else if (symbol->symbology == 103) {
+ symbol->symbology = BARCODE_HIBC_DM;
+ } else if (symbol->symbology == 105) {
+ symbol->symbology = BARCODE_HIBC_QR;
+ } else if (symbol->symbology == 107) {
+ symbol->symbology = BARCODE_HIBC_PDF;
+ } else if (symbol->symbology == 109) {
+ symbol->symbology = BARCODE_HIBC_MICPDF;
+ } else if (symbol->symbology == 111) {
+ symbol->symbology = BARCODE_HIBC_BLOCKF;
+ } else if ((symbol->symbology == 113) || (symbol->symbology == 114)) {
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "214: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ } else if ((symbol->symbology >= 117) && (symbol->symbology <= 127)) {
+ if (symbol->symbology != 121) { /* BARCODE_MAILMARK */
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "215: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ }
+ /* Everything from 128 up is Zint-specific */
+ } else if (symbol->symbology > BARCODE_LAST) {
+ warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "216: Symbology out of range");
+ if (warn_number >= ZINT_ERROR) {
+ return warn_number;
+ }
+ symbol->symbology = BARCODE_CODE128;
+ }
+ if (symbol->symbology == orig_symbology) { /* Should never happen */
+ return error_tag(symbol, ZINT_ERROR_ENCODING_PROBLEM, "000: Internal error"); /* Not reached */
+ }
+ }
+
+ if (seg_count > 1 && !supports_eci(symbol->symbology)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "775: Symbology does not support multiple segments");
+ }
+
+ /* Check ECI(s) */
+ for (i = 0; i < seg_count; i++) {
+ if (local_segs[i].eci) {
+ if (!supports_eci(symbol->symbology)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "217: Symbology does not support ECI switching");
+ }
+ if (local_segs[i].eci < 0 || local_segs[i].eci == 1 || local_segs[i].eci == 2 || local_segs[i].eci == 14
+ || local_segs[i].eci == 19 || local_segs[i].eci > 999999) {
+ sprintf(symbol->errtxt, "218: Invalid ECI code %d", local_segs[i].eci);
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, NULL);
+ }
+ } else {
+ have_zero_eci = 1;
+ }
+ }
+
+ /* Check other symbol fields */
+ if ((symbol->scale < 0.01f) || (symbol->scale > 100.0f)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "227: Scale out of range (0.01 to 100)");
+ }
+ if ((symbol->dot_size < 0.01f) || (symbol->dot_size > 20.0f)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "221: Dot size out of range (0.01 to 20)");
+ }
+
+ if ((symbol->height < 0.0f) || (symbol->height > 2000.0f)) { /* Allow for 44 row CODABLOCKF at 45X each */
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "765: Height out of range (0 to 2000)");
+ }
+ if ((symbol->guard_descent < 0.0f) || (symbol->guard_descent > 50.0f)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "769: Guard bar descent out of range (0 to 50)");
+ }
+ if ((symbol->whitespace_width < 0) || (symbol->whitespace_width > 100)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "766: Whitespace width out of range (0 to 100)");
+ }
+ if ((symbol->whitespace_height < 0) || (symbol->whitespace_height > 100)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "767: Whitespace height out of range (0 to 100)");
+ }
+ if ((symbol->border_width < 0) || (symbol->border_width > 100)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "768: Border width out of range (0 to 100)");
+ }
+
+ if (symbol->rows >= 200) { /* Check for stacking too many symbols */
+ return error_tag(symbol, ZINT_ERROR_TOO_LONG, "770: Too many stacked symbols");
+ }
+
+ if ((symbol->input_mode & 0x07) == GS1_MODE && !gs1_compliant(symbol->symbology)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "220: Selected symbology does not support GS1 mode");
+ }
+ if (seg_count > 1) {
+ /* Note: GS1_MODE not currently supported when using multiple segments */
+ if ((symbol->input_mode & 0x07) == GS1_MODE) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "776: GS1 mode not supported for multiple segments");
+ }
+ }
+
+ if ((symbol->input_mode & 0x07) == UNICODE_MODE) {
+ for (i = 0; i < seg_count; i++) {
+ if (!is_valid_utf8(local_segs[i].source, local_segs[i].length)) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "245: Invalid UTF-8 in input data");
+ }
+ }
+ }
+
+ local_sources = (unsigned char *) z_alloca(total_len + seg_count);
+
+ for (i = 0, local_source = local_sources; i < seg_count; i++) {
+ local_segs[i].source = local_source;
+ memcpy(local_segs[i].source, segs[i].source, local_segs[i].length);
+ local_segs[i].source[local_segs[i].length] = '\0';
+ local_source += local_segs[i].length + 1;
+ }
+
+ /* Start acting on input mode */
+ if (symbol->input_mode & ESCAPE_MODE) {
+ for (i = 0; i < seg_count; i++) {
+ error_number = escape_char_process(symbol, local_segs[i].source, &local_segs[i].length);
+ if (error_number != 0) { /* Only returns errors, not warnings */
+ return error_tag(symbol, error_number, NULL);
+ }
+ }
+ if (symbol->primary[0]) {
+ int primary_len = (int) strlen(symbol->primary);
+ error_number = escape_char_process(symbol, (unsigned char *) symbol->primary, &primary_len);
+ if (error_number != 0) { /* Only returns errors, not warnings */
+ return error_tag(symbol, error_number, NULL);
+ }
+ }
+ }
+
+ if ((symbol->input_mode & 0x07) == UNICODE_MODE) {
+ /* Only strip BOM on first segment */
+ strip_bom(local_segs[0].source, &local_segs[0].length);
+ }
+
+ if (((symbol->input_mode & 0x07) == GS1_MODE) || (check_force_gs1(symbol->symbology))) {
+ if (gs1_compliant(symbol->symbology)) {
+ /* Reduce input for composite and non-forced symbologies, others (EAN128 and RSS_EXP based) will
+ handle it themselves */
+ if (is_composite(symbol->symbology) || !check_force_gs1(symbol->symbology)) {
+ unsigned char *reduced = (unsigned char *) z_alloca(local_segs[0].length + 1);
+ error_number = gs1_verify(symbol, local_segs[0].source, local_segs[0].length, reduced);
+ if (error_number) {
+ static const char in_2d_comp[] = " in 2D component";
+ if (is_composite(symbol->symbology)
+ && strlen(symbol->errtxt) + strlen(in_2d_comp) < sizeof(symbol->errtxt)) {
+ strcat(symbol->errtxt, in_2d_comp);
+ }
+ error_number = error_tag(symbol, error_number, NULL);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+ warn_number = error_number; /* Override any previous warning (errtxt has been overwritten) */
+ }
+ ustrcpy(local_segs[0].source, reduced); /* Cannot contain NUL char */
+ local_segs[0].length = (int) ustrlen(reduced);
+ }
+ } else {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "220: Selected symbology does not support GS1 mode");
+ }
+ }
+
+ error_number = extended_or_reduced_charset(symbol, local_segs, seg_count);
+
+ if ((error_number == ZINT_ERROR_INVALID_DATA) && have_zero_eci && supports_eci(symbol->symbology)
+ && (symbol->input_mode & 0x07) == UNICODE_MODE) {
+ /* Try another ECI mode */
+ const int first_eci_set = get_best_eci_segs(symbol, local_segs, seg_count);
+ if (first_eci_set != 0) {
+ error_number = extended_or_reduced_charset(symbol, local_segs, seg_count);
+ /* Inclusion of ECI more noteworthy than other warnings, so overwrite (if any) */
+ if (error_number < ZINT_ERROR) {
+ error_number = ZINT_WARN_USES_ECI;
+ if (!(symbol->debug & ZINT_DEBUG_TEST)) {
+ sprintf(symbol->errtxt, "222: Encoded data includes ECI %d", first_eci_set);
+ }
+ if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", first_eci_set);
+ }
+ }
+ }
+
+ if (error_number == 0) {
+ error_number = warn_number; /* Already tagged */
+ } else {
+ error_number = error_tag(symbol, error_number, NULL);
+ }
+
+ if (error_number < ZINT_ERROR) {
+ if (symbol->height < 0.5f) { /* Absolute minimum */
+ (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/);
+ }
+ }
+
+ return error_number;
+}
+
+/* Helper for output routines to check `rotate_angle` and dottiness */
+static int check_output_args(struct zint_symbol *symbol, int rotate_angle) {
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ switch (rotate_angle) {
+ case 0:
+ case 90:
+ case 180:
+ case 270:
+ break;
+ default:
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "223: Invalid rotation angle");
+ break;
+ }
+
+ if ((symbol->output_options & BARCODE_DOTTY_MODE) && !(is_dotty(symbol->symbology))) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "224: Selected symbology cannot be rendered as dots");
+ }
+
+ return 0;
+}
+
+/* Output a previously encoded symbol to file `symbol->outfile` */
+int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
+ int error_number;
+ int len;
+
+ if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
+ return error_number; /* Already tagged */
+ }
+
+ len = (int) strlen(symbol->outfile);
+ if (len > 3) {
+ char output[4];
+ output[0] = symbol->outfile[len - 3];
+ output[1] = symbol->outfile[len - 2];
+ output[2] = symbol->outfile[len - 1];
+ output[3] = '\0';
+ to_upper((unsigned char *) output, 3);
+
+ if (!(strcmp(output, "PNG"))) {
+ error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE);
+
+ } else if (!(strcmp(output, "BMP"))) {
+ error_number = plot_raster(symbol, rotate_angle, OUT_BMP_FILE);
+
+ } else if (!(strcmp(output, "PCX"))) {
+ error_number = plot_raster(symbol, rotate_angle, OUT_PCX_FILE);
+
+ } else if (!(strcmp(output, "GIF"))) {
+ error_number = plot_raster(symbol, rotate_angle, OUT_GIF_FILE);
+
+ } else if (!(strcmp(output, "TIF"))) {
+ error_number = plot_raster(symbol, rotate_angle, OUT_TIF_FILE);
+
+ } else if (!(strcmp(output, "TXT"))) {
+ error_number = dump_plot(symbol);
+
+ } else if (!(strcmp(output, "EPS"))) {
+ error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE);
+
+ } else if (!(strcmp(output, "SVG"))) {
+ error_number = plot_vector(symbol, rotate_angle, OUT_SVG_FILE);
+
+ } else if (!(strcmp(output, "EMF"))) {
+ error_number = plot_vector(symbol, rotate_angle, OUT_EMF_FILE);
+
+ } else {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "225: Unknown output format");
+ }
+ } else {
+ return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "226: Unknown output format");
+ }
+
+ return error_tag(symbol, error_number, NULL);
+}
+
+/* Output a previously encoded symbol to memory as raster (`symbol->bitmap`) */
+int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
+ int error_number;
+
+ if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
+ return error_number; /* Already tagged */
+ }
+
+ error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER);
+ return error_tag(symbol, error_number, NULL);
+}
+
+/* Output a previously encoded symbol to memory as vector (`symbol->vector`) */
+int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) {
+ int error_number;
+
+ if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
+ return error_number; /* Already tagged */
+ }
+
+ error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER);
+ return error_tag(symbol, error_number, NULL);
+}
+
+/* Encode and output a symbol to file `symbol->outfile` */
+int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle) {
+ struct zint_seg segs[1];
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ segs[0].eci = symbol->eci;
+ segs[0].source = (unsigned char *) source;
+ segs[0].length = length;
+
+ return ZBarcode_Encode_Segs_and_Print(symbol, segs, 1, rotate_angle);
+}
+
+/* Encode a symbol with multiple ECI segments and output to file `symbol->outfile` */
+int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count,
+ int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Print(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+ return error_number;
+}
+
+/* Encode and output a symbol to memory as raster (`symbol->bitmap`) */
+int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *source, int length,
+ int rotate_angle) {
+ struct zint_seg segs[1];
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ segs[0].eci = symbol->eci;
+ segs[0].source = (unsigned char *) source;
+ segs[0].length = length;
+
+ return ZBarcode_Encode_Segs_and_Buffer(symbol, segs, 1, rotate_angle);
+}
+
+/* Encode a symbol with multiple ECI segments and output to memory as raster (`symbol->bitmap`) */
+int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count, int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Buffer(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+
+ return error_number;
+}
+
+/* Encode and output a symbol to memory as vector (`symbol->vector`) */
+int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, const unsigned char *source, int length,
+ int rotate_angle) {
+ struct zint_seg segs[1];
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ segs[0].eci = symbol->eci;
+ segs[0].source = (unsigned char *) source;
+ segs[0].length = length;
+
+ return ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, segs, 1, rotate_angle);
+}
+
+/* Encode a symbol with multiple ECI segments and output to memory as vector (`symbol->vector`) */
+int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count, int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+
+ return error_number;
+}
+
+/* Encode a barcode using input data from file `filename` */
+int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) {
+ FILE *file;
+ int file_opened = 0;
+ unsigned char *buffer;
+ long fileLen;
+ size_t n;
+ size_t nRead = 0;
+ int ret;
+
+ if (!symbol) return ZINT_ERROR_INVALID_DATA;
+
+ if (!filename) {
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "239: Filename NULL");
+ }
+
+ if (!strcmp(filename, "-")) {
+ file = stdin;
+ fileLen = ZINT_MAX_DATA_LEN;
+ } else {
+ file = fopen(filename, "rb");
+ if (!file) {
+ sprintf(symbol->errtxt, "229: Unable to read input file (%d: %.30s)", errno, strerror(errno));
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL);
+ }
+ file_opened = 1;
+
+ /* Get file length */
+ fseek(file, 0, SEEK_END);
+ fileLen = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ /* On many Linux distros ftell() returns LONG_MAX not -1 on error */
+ if (fileLen <= 0 || fileLen == LONG_MAX) {
+ fclose(file);
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "235: Input file empty or unseekable");
+ }
+ if (fileLen > ZINT_MAX_DATA_LEN) {
+ fclose(file);
+ return error_tag(symbol, ZINT_ERROR_TOO_LONG, "230: Input file too long");
+ }
+ }
+
+ /* Allocate memory */
+ buffer = (unsigned char *) malloc(fileLen);
+ if (!buffer) {
+ if (file_opened) {
+ fclose(file);
+ }
+ return error_tag(symbol, ZINT_ERROR_MEMORY, "231: Insufficient memory for file read buffer");
+ }
+
+ /* Read file contents into buffer */
+
+ do {
+ n = fread(buffer + nRead, 1, fileLen - nRead, file);
+ if (ferror(file)) {
+ sprintf(symbol->errtxt, "241: Input file read error (%d: %.30s)", errno, strerror(errno));
+ if (file_opened) {
+ fclose(file);
+ }
+ free(buffer);
+ return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL);
+ }
+ nRead += n;
+ } while (!feof(file) && (0 < n) && ((long) nRead < fileLen));
+
+ if (file_opened) {
+ fclose(file);
+ }
+ ret = ZBarcode_Encode(symbol, buffer, (int) nRead);
+ free(buffer);
+ return ret;
+}
+
+/* Encode a symbol using input data from file `filename` and output to file `symbol->outfile` */
+int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, const char *filename, int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_File(symbol, filename);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Print(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+
+ return error_number;
+}
+
+/* Encode a symbol using input data from file `filename` and output to memory as raster (`symbol->bitmap`) */
+int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char const *filename, int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_File(symbol, filename);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Buffer(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+
+ return error_number;
+}
+
+/* Encode a symbol using input data from file `filename` and output to memory as vector (`symbol->vector`) */
+int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const char *filename, int rotate_angle) {
+ int error_number;
+ int first_err;
+
+ error_number = ZBarcode_Encode_File(symbol, filename);
+ if (error_number >= ZINT_ERROR) {
+ return error_number;
+ }
+
+ first_err = error_number;
+ error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle);
+ if (error_number == 0) {
+ error_number = first_err;
+ }
+
+ return error_number;
+}
+
+/* Checks whether a symbology is supported */
+int ZBarcode_ValidID(int symbol_id) {
+
+ if (symbol_id <= 0 || symbol_id > BARCODE_LAST) {
+ return 0;
+ }
+
+ return barcode_funcs[symbol_id] != NULL;
+}
+
+/* Copy BARCODE_XXX name of `symbol_id` into `name` buffer, NUL-terminated.
+ Returns 0 if valid, non-zero (1 or -1) if not valid */
+int ZBarcode_BarcodeName(int symbol_id, char name[32]) {
+ struct item {
+ const char *name;
+ int define;
+ int val;
+ };
+ static const struct item data[] = {
+ { "", -1, 0 },
+ { "BARCODE_CODE11", BARCODE_CODE11, 1 },
+ { "BARCODE_C25STANDARD", BARCODE_C25STANDARD, 2 },
+ { "BARCODE_C25INTER", BARCODE_C25INTER, 3 },
+ { "BARCODE_C25IATA", BARCODE_C25IATA, 4 },
+ { "", -1, 5 },
+ { "BARCODE_C25LOGIC", BARCODE_C25LOGIC, 6 },
+ { "BARCODE_C25IND", BARCODE_C25IND, 7 },
+ { "BARCODE_CODE39", BARCODE_CODE39, 8 },
+ { "BARCODE_EXCODE39", BARCODE_EXCODE39, 9 },
+ { "", -1, 10 },
+ { "", -1, 11 },
+ { "", -1, 12 },
+ { "BARCODE_EANX", BARCODE_EANX, 13 },
+ { "BARCODE_EANX_CHK", BARCODE_EANX_CHK, 14 },
+ { "", -1, 15 },
+ { "BARCODE_GS1_128", BARCODE_GS1_128, 16 },
+ { "", -1, 17 },
+ { "BARCODE_CODABAR", BARCODE_CODABAR, 18 },
+ { "", -1, 19 },
+ { "BARCODE_CODE128", BARCODE_CODE128, 20 },
+ { "BARCODE_DPLEIT", BARCODE_DPLEIT, 21 },
+ { "BARCODE_DPIDENT", BARCODE_DPIDENT, 22 },
+ { "BARCODE_CODE16K", BARCODE_CODE16K, 23 },
+ { "BARCODE_CODE49", BARCODE_CODE49, 24 },
+ { "BARCODE_CODE93", BARCODE_CODE93, 25 },
+ { "", -1, 26 },
+ { "", -1, 27 },
+ { "BARCODE_FLAT", BARCODE_FLAT, 28 },
+ { "BARCODE_DBAR_OMN", BARCODE_DBAR_OMN, 29 },
+ { "BARCODE_DBAR_LTD", BARCODE_DBAR_LTD, 30 },
+ { "BARCODE_DBAR_EXP", BARCODE_DBAR_EXP, 31 },
+ { "BARCODE_TELEPEN", BARCODE_TELEPEN, 32 },
+ { "", -1, 33 },
+ { "BARCODE_UPCA", BARCODE_UPCA, 34 },
+ { "BARCODE_UPCA_CHK", BARCODE_UPCA_CHK, 35 },
+ { "", -1, 36 },
+ { "BARCODE_UPCE", BARCODE_UPCE, 37 },
+ { "BARCODE_UPCE_CHK", BARCODE_UPCE_CHK, 38 },
+ { "", -1, 39 },
+ { "BARCODE_POSTNET", BARCODE_POSTNET, 40 },
+ { "", -1, 41 },
+ { "", -1, 42 },
+ { "", -1, 43 },
+ { "", -1, 44 },
+ { "", -1, 45 },
+ { "", -1, 46 },
+ { "BARCODE_MSI_PLESSEY", BARCODE_MSI_PLESSEY, 47 },
+ { "", -1, 48 },
+ { "BARCODE_FIM", BARCODE_FIM, 49 },
+ { "BARCODE_LOGMARS", BARCODE_LOGMARS, 50 },
+ { "BARCODE_PHARMA", BARCODE_PHARMA, 51 },
+ { "BARCODE_PZN", BARCODE_PZN, 52 },
+ { "BARCODE_PHARMA_TWO", BARCODE_PHARMA_TWO, 53 },
+ { "BARCODE_CEPNET", BARCODE_CEPNET, 54 },
+ { "BARCODE_PDF417", BARCODE_PDF417, 55 },
+ { "BARCODE_PDF417COMP", BARCODE_PDF417COMP, 56 },
+ { "BARCODE_MAXICODE", BARCODE_MAXICODE, 57 },
+ { "BARCODE_QRCODE", BARCODE_QRCODE, 58 },
+ { "", -1, 59 },
+ { "BARCODE_CODE128B", BARCODE_CODE128B, 60 },
+ { "", -1, 61 },
+ { "", -1, 62 },
+ { "BARCODE_AUSPOST", BARCODE_AUSPOST, 63 },
+ { "", -1, 64 },
+ { "", -1, 65 },
+ { "BARCODE_AUSREPLY", BARCODE_AUSREPLY, 66 },
+ { "BARCODE_AUSROUTE", BARCODE_AUSROUTE, 67 },
+ { "BARCODE_AUSREDIRECT", BARCODE_AUSREDIRECT, 68 },
+ { "BARCODE_ISBNX", BARCODE_ISBNX, 69 },
+ { "BARCODE_RM4SCC", BARCODE_RM4SCC, 70 },
+ { "BARCODE_DATAMATRIX", BARCODE_DATAMATRIX, 71 },
+ { "BARCODE_EAN14", BARCODE_EAN14, 72 },
+ { "BARCODE_VIN", BARCODE_VIN, 73 },
+ { "BARCODE_CODABLOCKF", BARCODE_CODABLOCKF, 74 },
+ { "BARCODE_NVE18", BARCODE_NVE18, 75 },
+ { "BARCODE_JAPANPOST", BARCODE_JAPANPOST, 76 },
+ { "BARCODE_KOREAPOST", BARCODE_KOREAPOST, 77 },
+ { "", -1, 78 },
+ { "BARCODE_DBAR_STK", BARCODE_DBAR_STK, 79 },
+ { "BARCODE_DBAR_OMNSTK", BARCODE_DBAR_OMNSTK, 80 },
+ { "BARCODE_DBAR_EXPSTK", BARCODE_DBAR_EXPSTK, 81 },
+ { "BARCODE_PLANET", BARCODE_PLANET, 82 },
+ { "", -1, 83 },
+ { "BARCODE_MICROPDF417", BARCODE_MICROPDF417, 84 },
+ { "BARCODE_USPS_IMAIL", BARCODE_USPS_IMAIL, 85 },
+ { "BARCODE_PLESSEY", BARCODE_PLESSEY, 86 },
+ { "BARCODE_TELEPEN_NUM", BARCODE_TELEPEN_NUM, 87 },
+ { "", -1, 88 },
+ { "BARCODE_ITF14", BARCODE_ITF14, 89 },
+ { "BARCODE_KIX", BARCODE_KIX, 90 },
+ { "", -1, 91 },
+ { "BARCODE_AZTEC", BARCODE_AZTEC, 92 },
+ { "BARCODE_DAFT", BARCODE_DAFT, 93 },
+ { "", -1, 94 },
+ { "", -1, 95 },
+ { "BARCODE_DPD", BARCODE_DPD, 96 },
+ { "BARCODE_MICROQR", BARCODE_MICROQR, 97 },
+ { "BARCODE_HIBC_128", BARCODE_HIBC_128, 98 },
+ { "BARCODE_HIBC_39", BARCODE_HIBC_39, 99 },
+ { "", -1, 100 },
+ { "", -1, 101 },
+ { "BARCODE_HIBC_DM", BARCODE_HIBC_DM, 102 },
+ { "", -1, 103 },
+ { "BARCODE_HIBC_QR", BARCODE_HIBC_QR, 104 },
+ { "", -1, 105 },
+ { "BARCODE_HIBC_PDF", BARCODE_HIBC_PDF, 106 },
+ { "", -1, 107 },
+ { "BARCODE_HIBC_MICPDF", BARCODE_HIBC_MICPDF, 108 },
+ { "", -1, 109 },
+ { "BARCODE_HIBC_BLOCKF", BARCODE_HIBC_BLOCKF, 110 },
+ { "", -1, 111 },
+ { "BARCODE_HIBC_AZTEC", BARCODE_HIBC_AZTEC, 112 },
+ { "", -1, 113 },
+ { "", -1, 114 },
+ { "BARCODE_DOTCODE", BARCODE_DOTCODE, 115 },
+ { "BARCODE_HANXIN", BARCODE_HANXIN, 116 },
+ { "", -1, 117 },
+ { "", -1, 118 },
+ { "", -1, 119 },
+ { "", -1, 120 },
+ { "BARCODE_MAILMARK", BARCODE_MAILMARK, 121 },
+ { "", -1, 122 },
+ { "", -1, 123 },
+ { "", -1, 124 },
+ { "", -1, 125 },
+ { "", -1, 126 },
+ { "", -1, 127 },
+ { "BARCODE_AZRUNE", BARCODE_AZRUNE, 128 },
+ { "BARCODE_CODE32", BARCODE_CODE32, 129 },
+ { "BARCODE_EANX_CC", BARCODE_EANX_CC, 130 },
+ { "BARCODE_GS1_128_CC", BARCODE_GS1_128_CC, 131 },
+ { "BARCODE_DBAR_OMN_CC", BARCODE_DBAR_OMN_CC, 132 },
+ { "BARCODE_DBAR_LTD_CC", BARCODE_DBAR_LTD_CC, 133 },
+ { "BARCODE_DBAR_EXP_CC", BARCODE_DBAR_EXP_CC, 134 },
+ { "BARCODE_UPCA_CC", BARCODE_UPCA_CC, 135 },
+ { "BARCODE_UPCE_CC", BARCODE_UPCE_CC, 136 },
+ { "BARCODE_DBAR_STK_CC", BARCODE_DBAR_STK_CC, 137 },
+ { "BARCODE_DBAR_OMNSTK_CC", BARCODE_DBAR_OMNSTK_CC, 138 },
+ { "BARCODE_DBAR_EXPSTK_CC", BARCODE_DBAR_EXPSTK_CC, 139 },
+ { "BARCODE_CHANNEL", BARCODE_CHANNEL, 140 },
+ { "BARCODE_CODEONE", BARCODE_CODEONE, 141 },
+ { "BARCODE_GRIDMATRIX", BARCODE_GRIDMATRIX, 142 },
+ { "BARCODE_UPNQR", BARCODE_UPNQR, 143 },
+ { "BARCODE_ULTRA", BARCODE_ULTRA, 144 },
+ { "BARCODE_RMQR", BARCODE_RMQR, 145 },
+ { "BARCODE_BC412", BARCODE_BC412, 146 },
+ };
+
+ name[0] = '\0';
+
+ if (!ZBarcode_ValidID(symbol_id)) {
+ return 1;
+ }
+ assert(symbol_id >= 0 && symbol_id < ARRAY_SIZE(data) && data[symbol_id].name[0]);
+
+ /* Self-check, shouldn't happen */
+ if (data[symbol_id].val != symbol_id || (data[symbol_id].define != -1 && data[symbol_id].define != symbol_id)) {
+ assert(0); /* Not reached */
+ return -1;
+ }
+
+ strcpy(name, data[symbol_id].name);
+
+ return 0;
+}
+
+/* Return the capability flags for symbology `symbol_id` that match `cap_flag` */
+unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) {
+ unsigned int result = 0;
+
+ if (!ZBarcode_ValidID(symbol_id)) {
+ return 0;
+ }
+
+ if ((cap_flag & ZINT_CAP_HRT) && has_hrt(symbol_id)) {
+ result |= ZINT_CAP_HRT;
+ }
+ if ((cap_flag & ZINT_CAP_STACKABLE) && is_stackable(symbol_id)) {
+ result |= ZINT_CAP_STACKABLE;
+ }
+ if ((cap_flag & ZINT_CAP_EXTENDABLE) && is_extendable(symbol_id)) {
+ result |= ZINT_CAP_EXTENDABLE;
+ }
+ if ((cap_flag & ZINT_CAP_COMPOSITE) && is_composite(symbol_id)) {
+ result |= ZINT_CAP_COMPOSITE;
+ }
+ if ((cap_flag & ZINT_CAP_ECI) && supports_eci(symbol_id)) {
+ result |= ZINT_CAP_ECI;
+ }
+ if ((cap_flag & ZINT_CAP_GS1) && gs1_compliant(symbol_id)) {
+ result |= ZINT_CAP_GS1;
+ }
+ if ((cap_flag & ZINT_CAP_DOTTY) && is_dotty(symbol_id)) {
+ result |= ZINT_CAP_DOTTY;
+ }
+ if (cap_flag & ZINT_CAP_QUIET_ZONES) {
+ switch (symbol_id) { /* See `out_quiet_zones()` in "output.c" */
+ case BARCODE_CODE16K:
+ case BARCODE_CODE49:
+ case BARCODE_CODABLOCKF:
+ case BARCODE_HIBC_BLOCKF:
+ case BARCODE_ITF14:
+ case BARCODE_EANX:
+ case BARCODE_EANX_CHK:
+ case BARCODE_EANX_CC:
+ case BARCODE_ISBNX:
+ case BARCODE_UPCA:
+ case BARCODE_UPCA_CHK:
+ case BARCODE_UPCA_CC:
+ case BARCODE_UPCE:
+ case BARCODE_UPCE_CHK:
+ case BARCODE_UPCE_CC:
+ result |= ZINT_CAP_QUIET_ZONES;
+ break;
+ }
+ }
+ if ((cap_flag & ZINT_CAP_FIXED_RATIO) && is_fixed_ratio(symbol_id)) {
+ result |= ZINT_CAP_FIXED_RATIO;
+ }
+ if (cap_flag & ZINT_CAP_READER_INIT) {
+ /* Note does not include HIBC versions */
+ switch (symbol_id) {
+ case BARCODE_CODE128: /* Note does not include GS1_128 or NVE18 */
+ case BARCODE_CODE128B:
+ case BARCODE_CODE16K:
+ case BARCODE_CODABLOCKF:
+ case BARCODE_PDF417:
+ case BARCODE_PDF417COMP:
+ case BARCODE_DATAMATRIX:
+ case BARCODE_MICROPDF417:
+ case BARCODE_AZTEC:
+ case BARCODE_DOTCODE:
+ case BARCODE_GRIDMATRIX:
+ case BARCODE_ULTRA:
+ result |= ZINT_CAP_READER_INIT;
+ break;
+ }
+ }
+ if (cap_flag & ZINT_CAP_FULL_MULTIBYTE) {
+ switch (symbol_id) {
+ case BARCODE_QRCODE:
+ case BARCODE_MICROQR:
+ /* case BARCODE_HIBC_QR: Note character set restricted to ASCII subset */
+ /* case BARCODE_UPNQR: Note does not use Kanji mode */
+ case BARCODE_RMQR:
+ case BARCODE_HANXIN:
+ case BARCODE_GRIDMATRIX:
+ result |= ZINT_CAP_FULL_MULTIBYTE;
+ break;
+ }
+ }
+ if (cap_flag & ZINT_CAP_MASK) {
+ switch (symbol_id) {
+ case BARCODE_QRCODE:
+ case BARCODE_MICROQR:
+ case BARCODE_UPNQR:
+ case BARCODE_HANXIN:
+ case BARCODE_DOTCODE:
+ result |= ZINT_CAP_MASK;
+ break;
+ }
+ }
+ if (cap_flag & ZINT_CAP_STRUCTAPP) {
+ switch (symbol_id) {
+ case BARCODE_PDF417:
+ case BARCODE_PDF417COMP:
+ case BARCODE_MAXICODE:
+ case BARCODE_QRCODE: /* Note does not include MICROQR, UPNQR or rMQR */
+ case BARCODE_DATAMATRIX:
+ case BARCODE_MICROPDF417:
+ case BARCODE_AZTEC:
+ case BARCODE_HIBC_DM:
+ case BARCODE_HIBC_QR:
+ case BARCODE_HIBC_PDF:
+ case BARCODE_HIBC_MICPDF:
+ case BARCODE_HIBC_AZTEC:
+ case BARCODE_DOTCODE:
+ case BARCODE_CODEONE:
+ case BARCODE_GRIDMATRIX:
+ case BARCODE_ULTRA:
+ result |= ZINT_CAP_STRUCTAPP;
+ break;
+ }
+ }
+ if ((cap_flag & ZINT_CAP_COMPLIANT_HEIGHT) && !is_fixed_ratio(symbol_id)) {
+ switch (symbol_id) {
+ /* These don't have a compliant height defined */
+ case BARCODE_CODE11: /* TODO: Find doc */
+ case BARCODE_C25STANDARD: /* For C25 only have doc for C25INTER */
+ case BARCODE_C25IATA:
+ case BARCODE_C25LOGIC:
+ case BARCODE_C25IND:
+ case BARCODE_CODE128: /* Left to application */
+ case BARCODE_CODE128B:
+ case BARCODE_DPLEIT: /* TODO: Find doc */
+ case BARCODE_DPIDENT: /* TODO: Find doc */
+ case BARCODE_FLAT: /* TODO: Find doc */
+ case BARCODE_MSI_PLESSEY: /* TODO: Find doc */
+ case BARCODE_PDF417: /* Has compliant height but already warns & uses for default */
+ case BARCODE_PDF417COMP:
+ case BARCODE_VIN: /* Spec unlikely */
+ case BARCODE_KOREAPOST: /* TODO: Find doc */
+ case BARCODE_MICROPDF417: /* See PDF417 */
+ case BARCODE_PLESSEY: /* TODO: Find doc */
+ case BARCODE_DAFT: /* Generic */
+ case BARCODE_HIBC_128: /* See CODE128 */
+ case BARCODE_HIBC_PDF: /* See PDF417 */
+ case BARCODE_HIBC_MICPDF: /* See PDF417 */
+ break;
+ default:
+ result |= ZINT_CAP_COMPLIANT_HEIGHT;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Rendering support, initially added by Sam Lown.
+ * Plot to gLabels - backported from 2.6.7 by brozkeff 2022-11-25
+ */
+int ZBarcode_Render(struct zint_symbol *symbol, const float width, const float height) {
+ // Send the request to the render_plot method
+ return render_plot(symbol, width, height);
+}
+
+
+/* Return the version of Zint linked to */
+int ZBarcode_Version(void) {
+ if (ZINT_VERSION_BUILD) {
+ return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE * 10
+ + ZINT_VERSION_BUILD;
+ }
+ return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE;
+}
+
+/* vim: set ts=4 sw=4 et : */
diff --git a/render.c b/render.c
new file mode 100755
index 0000000..98184fb
--- /dev/null
+++ b/render.c
@@ -0,0 +1,859 @@
+/*
+ * render.c - Generic Rendered Format
+ *
+ * Initiall written by Sam Lown for use in gLabels. Converts encoded
+ * data into a generic internal structure of lines and characters
+ * usable in external applications.
+ Backported from 2.6.7 to 2.11 by brozkeff 2022-11-25
+ */
+
+/*
+ libzint - the open source barcode library
+ Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the project nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ */
+
+#include <locale.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef _MSC_VER
+#include <malloc.h>
+#endif
+#include "common.h"
+
+#define GL_CONST 2.8346
+
+struct zint_render_line *render_plot_create_line(float x, float y, float width, float length);
+int render_plot_add_line(struct zint_symbol *symbol, struct zint_render_line *line, struct zint_render_line **last_line);
+struct zint_render_ring *render_plot_create_ring(float x, float y, float radius, float line_width);
+int render_plot_add_ring(struct zint_symbol *symbol, struct zint_render_ring *ring, struct zint_render_ring **last_ring);
+struct zint_render_hexagon *render_plot_create_hexagon(float x, float y, float height);
+int render_plot_add_hexagon(struct zint_symbol *symbol, struct zint_render_hexagon *hexagon, struct zint_render_hexagon **last_hexagon);
+
+int render_plot_add_string(struct zint_symbol *symbol, unsigned char *text, float x, float y, float fsize, float width, struct zint_render_string **last_string);
+void render_free(struct zint_symbol *symbol);
+
+int render_plot(struct zint_symbol *symbol, float width, float height) {
+ struct zint_render *render;
+ struct zint_render_line *line, *last_line = NULL;
+ struct zint_render_string *last_string = NULL;
+ struct zint_render_ring *last_ring = NULL;
+ struct zint_render_hexagon *last_hexagon = NULL;
+
+ int i, r, latch;
+ float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0;
+ // int error_number = 0;
+ int text_offset, text_height, xoffset, yoffset, textdone, main_symbol_width_x, addon_width_x;
+ char addon[6];
+ int large_bar_count, symbol_lead_in, total_symbol_width_x, total_area_width_x;
+ float addon_text_posn;
+ float default_text_posn;
+ float scaler;
+ const char *locale = NULL;
+ int hide_text = 0;
+ float symbol_aspect = 1;
+ float x_dimension;
+ int upceanflag = 0;
+
+ // Free any previous rendering structures
+ render_free(symbol);
+ // Allocate memory for the rendered version
+ render = symbol->rendered = (struct zint_render *) malloc(sizeof (struct zint_render));
+ if (!symbol->rendered) return ZINT_ERROR_MEMORY;
+ render->lines = NULL;
+ render->strings = NULL;
+ render->rings = NULL;
+ render->hexagons = NULL;
+
+ locale = setlocale(LC_ALL, "C");
+
+ row_height = 0;
+ textdone = 0;
+ textpos = 0.0;
+ main_symbol_width_x = symbol->width;
+ strcpy(addon, "");
+ symbol_lead_in = 0;
+ addon_text_posn = 0.0;
+ addon_width_x = 0;
+
+ /*
+ * Determine if there will be any addon texts and text height
+ */
+ latch = 0;
+ r = 0;
+ /* Isolate add-on text */
+ if (is_extendable(symbol->symbology)) {
+ for(i = 0; i < (int)ustrlen(symbol->text); i++) {
+ if (latch == 1) {
+ addon[r] = symbol->text[i];
+ r++;
+ }
+ if (symbol->text[i] == '+') {
+ latch = 1;
+ }
+ }
+ }
+ addon[r] = '\0';
+
+
+ /*
+ * Calculate the width of the barcode, especially if there are any extra
+ * borders or white space to add.
+ */
+
+ while (!(module_is_set(symbol, symbol->rows - 1, symbol_lead_in))) {
+ symbol_lead_in++;
+ }
+
+ /* Certain symbols need whitespace otherwise characters get chopped off the sides */
+ if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
+ || (symbol->symbology == BARCODE_ISBNX)) {
+ switch (ustrlen(symbol->text)) {
+ case 13: /* EAN 13 */
+ case 16:
+ case 19:
+ if (symbol->whitespace_width == 0) {
+ symbol->whitespace_width = 10;
+ }
+ main_symbol_width_x = 96 + symbol_lead_in;
+ upceanflag = 13;
+ break;
+ case 2:
+ main_symbol_width_x = 22 + symbol_lead_in;
+ upceanflag = 2;
+ break;
+ case 5:
+ main_symbol_width_x = 49 + symbol_lead_in;
+ upceanflag = 5;
+ break;
+ default:
+ main_symbol_width_x = 68 + symbol_lead_in;
+ upceanflag = 8;
+ }
+ switch (ustrlen(symbol->text)) {
+ case 11:
+ case 16:
+ /* EAN-2 add-on */
+ addon_width_x = 31;
+ break;
+ case 14:
+ case 19:
+ /* EAN-5 add-on */
+ addon_width_x = 58;
+ break;
+ }
+ }
+ else if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
+ upceanflag = 12;
+ if (symbol->whitespace_width < 10) {
+ symbol->whitespace_width = 10;
+ main_symbol_width_x = 96 + symbol_lead_in;
+ }
+ switch (ustrlen(symbol->text)) {
+ case 15:
+ /* EAN-2 add-on */
+ addon_width_x = 31;
+ break;
+ case 18:
+ /* EAN-5 add-on */
+ addon_width_x = 58;
+ break;
+ }
+ }
+ else if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
+ upceanflag = 6;
+ if (symbol->whitespace_width == 0) {
+ symbol->whitespace_width = 10;
+ main_symbol_width_x = 51 + symbol_lead_in;
+ }
+ switch (ustrlen(symbol->text)) {
+ case 11:
+ /* EAN-2 add-on */
+ addon_width_x = 31;
+ break;
+ case 14:
+ /* EAN-5 add-on */
+ addon_width_x = 58;
+ break;
+ }
+ }
+
+ if ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0)) {
+ hide_text = 1;
+ text_height = text_offset = 0.0;
+ }
+ else {
+ text_height = upceanflag ? 11.0 : 9.0;
+ text_offset = 2.0;
+ }
+ if (symbol->output_options & SMALL_TEXT)
+ text_height *= 0.8;
+
+ total_symbol_width_x = 0.0 + main_symbol_width_x + addon_width_x;
+ total_area_width_x = total_symbol_width_x + (2 * (symbol->border_width + symbol->whitespace_width));
+
+ xoffset = symbol->border_width + symbol->whitespace_width;
+ yoffset = symbol->border_width;
+
+
+ // Determine if height should be overridden
+ large_bar_count = 0;
+ preset_height = 0.0;
+ for (i = 0; i < symbol->rows; i++) {
+ preset_height += symbol->row_height[i];
+ if (symbol->row_height[i] == 0) {
+ large_bar_count++;
+ }
+ }
+
+
+ /* Set minimum size of symbol */
+ /* Barcode must be at least 2mm high by 2mm across */
+ if (width < (2.0 * GL_CONST)) {
+ width = (2.0 * GL_CONST);
+ }
+ x_dimension = width / total_area_width_x / GL_CONST;
+ if (height < ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + 2.0) * GL_CONST) {
+ height = ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + 2.0) * GL_CONST;
+ }
+
+ if (symbol->symbology == BARCODE_CODABAR) {
+ /* The minimum X-dimension of Codabar is 0.191mm. The minimum bar height is 5mm */
+ if (x_dimension < 0.191) {
+ x_dimension = 0.191;
+ width = 0.191 * GL_CONST * total_area_width_x;
+ }
+ if (height < ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + 5.0) * GL_CONST) {
+ height = ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + 5.0) * GL_CONST;
+ }
+ }
+ else if (symbol->symbology == BARCODE_CODE49) {
+ /* The minimum X-dimension of Code 49 is 0.191mm */
+ if (x_dimension < 0.191) {
+ float encoded_symbol_aspect;
+ x_dimension = 0.191;
+ width = 0.191 * GL_CONST * total_area_width_x;
+ encoded_symbol_aspect = total_area_width_x;
+ encoded_symbol_aspect /= (preset_height + (2 * yoffset) + text_offset + text_height);
+ height = width / encoded_symbol_aspect;
+ }
+ }
+
+ if (upceanflag != 0) {
+ /* The X-dimension of UPC/EAN symbols is fixed at 0.330mm */
+ /* The phrase before is questionable. It may scale in certain percentages (80% - 200%).
+ see https://internationalbarcodes.com/ean-13-specifications/ */
+ // Can now cope with sizes between 80% and 200%, enforces correct aspect ratio
+ /* NOTE: This code will need adjustment before it correctly deals with composite symbols */
+ //x_dimension = 0.330;
+ if (x_dimension < 0.26) {
+ x_dimension = 0.26;
+ }
+ if (x_dimension > 0.66) {
+ x_dimension = 0.66;
+ }
+ width = x_dimension * GL_CONST * total_area_width_x;
+
+ switch (upceanflag) {
+ case 6:
+ case 12:
+ case 13:
+ /* UPC-A, UPC-E and EAN-13 */
+ /* Height of bars should be 22.85mm */
+ height = ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + (22.85 * (x_dimension / 0.33))) * GL_CONST;
+ break;
+ case 8:
+ /* EAN-8 */
+ /* Height of bars should be 18.23mm */
+ height = ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + (18.23 * (x_dimension / 0.33))) * GL_CONST;
+ break;
+ default:
+ /* EAN-2 and EAN-5 */
+ /* Height of bars should be 21.10mm */
+ height = ((x_dimension * ((2 * symbol->border_width) + text_offset + text_height)) + (21.10 * (x_dimension / 0.33))) * GL_CONST;
+ }
+ }
+
+ if (symbol->symbology == BARCODE_ONECODE) {
+ /* The size of USPS Intelligent Mail barcode is fixed */
+ x_dimension = 0.508;
+ width = 0.508 * GL_CONST * total_area_width_x;
+ height = 4.064 * GL_CONST;
+ }
+ else if ((symbol->symbology == BARCODE_POSTNET) || (symbol->symbology == BARCODE_PLANET)) {
+ /* The size of PostNet and PLANET are fized */
+ x_dimension = 0.508;
+ width = 0.508 * GL_CONST * total_area_width_x;
+ height = 2.921 * GL_CONST;
+ }
+ else if (((symbol->symbology == BARCODE_AUSPOST) || (symbol->symbology == BARCODE_AUSREPLY)) ||
+ ((symbol->symbology == BARCODE_AUSROUTE) || (symbol->symbology == BARCODE_AUSREDIRECT))) {
+ /* Australia Post use the same sizes as USPS */
+ x_dimension = 0.508;
+ width = 0.508 * GL_CONST * total_area_width_x;
+ height = 4.064 * GL_CONST;
+ }
+ else if ((symbol->symbology == BARCODE_RM4SCC) || (symbol->symbology == BARCODE_KIX)) {
+ /* Royal Mail and KIX Code uses 22 bars per inch */
+ x_dimension = 0.577;
+ width = 0.577 * GL_CONST * total_area_width_x;
+ height = 5.22 * GL_CONST;
+ }
+
+
+ if (large_bar_count == 0) {
+ float required_aspect = width / height;
+ symbol_aspect = (total_symbol_width_x + (2 * xoffset)) / (preset_height + (2 * yoffset) + text_offset + text_height);
+ symbol->height = (int) preset_height;
+ if (required_aspect > symbol_aspect) {
+ /* the area is too wide */
+ scaler = height / (preset_height + (2 * yoffset) + text_offset + text_height);
+ render->width = symbol_aspect * height;
+ render->height = height;
+ } else {
+ /* the area is too high */
+ scaler = width / (total_symbol_width_x + (2 * xoffset));
+ render->width = width;
+ render->height = width / symbol_aspect;
+ }
+ } else {
+ scaler = width / (total_symbol_width_x + (2 * xoffset));
+ symbol->height = (int) ((height / scaler) - ((2 * yoffset) + text_offset + text_height));
+
+ render->width = width;
+ render->height = height;
+ }
+ large_bar_height = (symbol->height - preset_height) / large_bar_count;
+
+ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
+ default_text_posn = (symbol->height + text_offset + symbol->border_width + symbol->border_width) * scaler;
+ } else {
+ default_text_posn = (symbol->height + text_offset + symbol->border_width) * scaler;
+ }
+
+
+ if (symbol->symbology == BARCODE_MAXICODE) {
+ struct zint_render_ring *ring;
+ /* Maxicode is a fixed size */
+ scaler = GL_CONST; /* Converts from millimeters to the scale used by glabels */
+ render->width = 28.16 * scaler;
+ render->height = 26.86 * scaler;
+
+ /* Central bullseye pattern */
+ ring = render_plot_create_ring(13.64 * scaler, 13.43 * scaler, 0.85 * scaler, 0.67 * scaler);
+ render_plot_add_ring(symbol, ring, &last_ring);
+ ring = render_plot_create_ring(13.64 * scaler, 13.43 * scaler, 2.20 * scaler, 0.67 * scaler);
+ render_plot_add_ring(symbol, ring, &last_ring);
+ ring = render_plot_create_ring(13.64 * scaler, 13.43 * scaler, 3.54 * scaler, 0.67 * scaler);
+ render_plot_add_ring(symbol, ring, &last_ring);
+
+ /* Hexagons */
+ for (r = 0; r < symbol->rows; r++) {
+ for (i = 0; i < symbol->width; i++) {
+ if (module_is_set(symbol, r, i)) {
+ struct zint_render_hexagon *hexagon = render_plot_create_hexagon(((i * 0.88) + ((r & 1) ? 1.76 : 1.32)) * scaler, ((r * 0.76) + 0.76) * scaler, 1. * scaler);
+ render_plot_add_hexagon(symbol, hexagon, &last_hexagon);
+ }
+ }
+ }
+
+ } else {
+ /* everything else uses rectangles (or squares) */
+ /* Works from the bottom of the symbol up */
+ int addon_latch = 0;
+
+ for (r = 0; r < symbol->rows; r++) {
+ int this_row = r;
+ if (symbol->row_height[this_row] == 0) {
+ row_height = large_bar_height;
+ } else {
+ row_height = symbol->row_height[this_row];
+ }
+ row_posn = 0;
+ for (i = 0; i < r; i++) {
+ if (symbol->row_height[i] == 0) {
+ row_posn += large_bar_height;
+ } else {
+ row_posn += symbol->row_height[i];
+ }
+ }
+ row_posn += yoffset;
+
+ i = 0;
+ if (module_is_set(symbol, this_row, 0)) {
+ latch = 1;
+ } else {
+ latch = 0;
+ }
+
+ do {
+ int block_width = 0;
+ do {
+ block_width++;
+ } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
+ if ((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_symbol_width_x)) {
+ addon_text_posn = row_posn * scaler;
+ addon_latch = 1;
+ }
+ if (latch == 1) {
+ /* a bar */
+ if (addon_latch == 0) {
+ line = render_plot_create_line((i + xoffset) * scaler, (row_posn) * scaler, block_width * scaler, row_height * scaler);
+ } else {
+ line = render_plot_create_line((i + xoffset) * scaler, (row_posn + 10.0) * scaler, block_width * scaler, (row_height - 5.0) * scaler);
+ }
+ latch = 0;
+
+ render_plot_add_line(symbol, line, &last_line);
+ } else {
+ /* a space */
+ latch = 1;
+ }
+ i += block_width;
+
+ } while (i < symbol->width);
+ }
+ }
+ /* That's done the actual data area, everything else is human-friendly */
+
+
+ /* Add the text */
+ xoffset -= symbol_lead_in;
+ row_posn = (row_posn + large_bar_height) * scaler;
+
+ if (!hide_text) {
+ char textpart[10];
+ float textwidth;
+ if (upceanflag == 8) {
+ /* guard bar extensions and text formatting for EAN-8 */
+ i = 0;
+ for (line = symbol->rendered->lines; line != NULL; line = line->next) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 10:
+ case 11:
+ case 20:
+ case 21:
+ line->length += (5.0 * scaler);
+ break;
+ }
+ i++;
+ }
+
+ for (i = 0; i < 4; i++) {
+ textpart[i] = symbol->text[i];
+ }
+ textpart[4] = '\0';
+ textpos = 17;
+ textwidth = 4.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ for (i = 0; i < 4; i++) {
+ textpart[i] = symbol->text[i + 4];
+ }
+ textpart[4] = '\0';
+ textpos = 50;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ textdone = 1;
+ switch (strlen(addon)) {
+ case 2:
+ textpos = xoffset + 86;
+ textwidth = 2.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ case 5:
+ textpos = xoffset + 100;
+ textwidth = 5.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ }
+
+ }
+
+ if (upceanflag == 13) {
+ /* guard bar extensions and text formatting for EAN-13 */
+ i = 0;
+ for (line = symbol->rendered->lines; line != NULL; line = line->next) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 14:
+ case 15:
+ case 28:
+ case 29:
+ line->length += (5.0 * scaler);
+ break;
+ }
+ i++;
+ }
+
+ textpart[0] = symbol->text[0];
+ textpart[1] = '\0';
+ textpos = -5; // 7
+ textwidth = 8.5;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+
+ for (i = 0; i < 6; i++) {
+ textpart[i] = symbol->text[i + 1];
+ }
+ textpart[6] = '\0';
+ textpos = 25;
+ textwidth = 6.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ for (i = 0; i < 6; i++) {
+ textpart[i] = symbol->text[i + 7];
+ }
+ textpart[6] = '\0';
+ textpos = 72;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ textdone = 1;
+ switch (strlen(addon)) {
+ case 2:
+ textpos = xoffset + 114;
+ textwidth = 2.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ case 5:
+ textpos = xoffset + 128;
+ textwidth = 5.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ }
+ }
+
+ if (upceanflag == 12) {
+ /* guard bar extensions and text formatting for UPCA */
+ i = 0;
+ for (line = symbol->rendered->lines; line != NULL; line = line->next) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 14:
+ case 15:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ line->length += (5.0 * scaler);
+ break;
+ }
+ i++;
+ }
+
+ textpart[0] = symbol->text[0];
+ textpart[1] = '\0';
+ textpos = -5;
+ textwidth = 6.2;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn + (2.0 * scaler), text_height * (8.0 / 11.0) * scaler, textwidth * scaler, &last_string);
+ for (i = 0; i < 5; i++) {
+ textpart[i] = symbol->text[i + 1];
+ }
+ textpart[5] = '\0';
+ textpos = 27;
+ textwidth = 5.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ for (i = 0; i < 5; i++) {
+ textpart[i] = symbol->text[i + 6];
+ }
+ textpos = 68;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ textpart[0] = symbol->text[11];
+ textpart[1] = '\0';
+ textpos = 100;
+ textwidth = 6.2;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn + (2.0 * scaler), text_height * (8.0 / 11.0) * scaler, textwidth * scaler, &last_string);
+ textdone = 1;
+ switch (strlen(addon)) {
+ case 2:
+ textpos = xoffset + 116;
+ textwidth = 2.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ case 5:
+ textpos = xoffset + 130;
+ textwidth = 5.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ }
+ }
+
+ if (upceanflag == 6) {
+ /* guard bar extensions and text formatting for UPCE */
+ i = 0;
+ for (line = symbol->rendered->lines; line != NULL; line = line->next) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 14:
+ case 15:
+ case 16:
+ line->length += (5.0 * scaler);
+ break;
+ }
+ i++;
+ }
+
+ textpart[0] = symbol->text[0];
+ textpart[1] = '\0';
+ textpos = -5;
+ textwidth = 6.2;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn + (2.0 * scaler), text_height * (8.0 / 11.0) * scaler, textwidth * scaler, &last_string);
+ for (i = 0; i < 6; i++) {
+ textpart[i] = symbol->text[i + 1];
+ }
+ textpart[6] = '\0';
+ textpos = 24;
+ textwidth = 6.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn, text_height * scaler, textwidth * scaler, &last_string);
+ textpart[0] = symbol->text[7];
+ textpart[1] = '\0';
+ textpos = 55;
+ textwidth = 6.2;
+ render_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset) * scaler, default_text_posn + (2.0 * scaler), text_height * (8.0 / 11.0) * scaler, textwidth * scaler, &last_string);
+ textdone = 1;
+ switch (strlen(addon)) {
+ case 2:
+ textpos = xoffset + 70;
+ textwidth = 2.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ case 5:
+ textpos = xoffset + 84;
+ textwidth = 5.0 * 8.5;
+ render_plot_add_string(symbol, (unsigned char *) addon, textpos * scaler, addon_text_posn * scaler, text_height * scaler, textwidth * scaler, &last_string);
+ break;
+ }
+ }
+
+ /* Put normal human readable text at the bottom (and centered) */
+ if (textdone == 0) {
+ // caculate start xoffset to center text
+ render_plot_add_string(symbol, symbol->text, ((symbol->width / 2.0) + xoffset) * scaler, default_text_posn, text_height * scaler, symbol->width * scaler, &last_string);
+ }
+ }
+
+ switch (symbol->symbology) {
+ case BARCODE_MAXICODE:
+ /* Do nothing! */
+ break;
+ default:
+ if ((symbol->output_options & BARCODE_BIND) != 0) {
+ if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
+ /* row binding */
+ for (r = 1; r < symbol->rows; r++) {
+ line = render_plot_create_line(xoffset * scaler, ((r * row_height) + yoffset - 1) * scaler, symbol->width * scaler, 2.0 * scaler);
+ render_plot_add_line(symbol, line, &last_line);
+ }
+ }
+ }
+ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
+ line = render_plot_create_line(0, 0, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
+ render_plot_add_line(symbol, line, &last_line);
+ line = render_plot_create_line(0, (symbol->height + symbol->border_width) * scaler, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
+ render_plot_add_line(symbol, line, &last_line);
+ }
+ if (symbol->output_options & BARCODE_BOX) {
+ /* side bars */
+ line = render_plot_create_line(0, 0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
+ render_plot_add_line(symbol, line, &last_line);
+ line = render_plot_create_line((symbol->width + xoffset + xoffset - symbol->border_width) * scaler, 0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
+ render_plot_add_line(symbol, line, &last_line);
+ }
+ break;
+ }
+
+ if (locale)
+ setlocale(LC_ALL, locale);
+
+ return 1;
+}
+
+/*
+ * Create a new line with its memory allocated ready for adding to the
+ * rendered structure.
+ *
+ * This is much quicker than writing out each line manually (in some cases!)
+ */
+struct zint_render_line *render_plot_create_line(float x, float y, float width, float length) {
+ struct zint_render_line *line;
+
+ line = (struct zint_render_line*) malloc(sizeof (struct zint_render_line));
+ if (!line) return NULL;
+
+ line->next = NULL;
+ line->x = x;
+ line->y = y;
+ line->width = width;
+ line->length = length;
+
+ return line;
+}
+
+/*
+ * Add the line to the current rendering and update the last line's
+ * next value.
+ */
+int render_plot_add_line(struct zint_symbol *symbol, struct zint_render_line *line, struct zint_render_line **last_line) {
+ if (!line) return ZINT_ERROR_MEMORY;
+ if (*last_line)
+ (*last_line)->next = line;
+ else
+ symbol->rendered->lines = line; // first line
+
+ *last_line = line;
+ return 1;
+}
+
+struct zint_render_ring *render_plot_create_ring(float x, float y, float radius, float line_width) {
+ struct zint_render_ring *ring;
+
+ ring = (struct zint_render_ring *) malloc(sizeof (struct zint_render_ring));
+ if (!ring) return NULL;
+ ring->next = NULL;
+ ring->x = x;
+ ring->y = y;
+ ring->radius = radius;
+ ring->line_width = line_width;
+
+ return ring;
+}
+
+int render_plot_add_ring(struct zint_symbol *symbol, struct zint_render_ring *ring, struct zint_render_ring **last_ring) {
+ if (!ring) return ZINT_ERROR_MEMORY;
+ if (*last_ring)
+ (*last_ring)->next = ring;
+ else
+ symbol->rendered->rings = ring; // first ring
+
+ *last_ring = ring;
+ return 1;
+}
+
+struct zint_render_hexagon *render_plot_create_hexagon(float x, float y, float height) {
+ struct zint_render_hexagon *hexagon;
+
+ hexagon = (struct zint_render_hexagon*) malloc(sizeof (struct zint_render_hexagon));
+ if (!hexagon) return NULL;
+ hexagon->next = NULL;
+ hexagon->x = x;
+ hexagon->y = y;
+ hexagon->height = height;
+
+ return hexagon;
+}
+
+int render_plot_add_hexagon(struct zint_symbol *symbol, struct zint_render_hexagon *hexagon, struct zint_render_hexagon **last_hexagon) {
+ if (!hexagon) return ZINT_ERROR_MEMORY;
+ if (*last_hexagon)
+ (*last_hexagon)->next = hexagon;
+ else
+ symbol->rendered->hexagons = hexagon; // first hexagon
+
+ *last_hexagon = hexagon;
+ return 1;
+}
+
+/*
+ * Add a string structure to the symbol.
+ * Coordinates assumed to be from top-center.
+ */
+int render_plot_add_string(struct zint_symbol *symbol,
+ unsigned char *text, float x, float y, float fsize, float width,
+ struct zint_render_string **last_string) {
+ struct zint_render_string *string;
+
+ string = (struct zint_render_string*) malloc(sizeof (struct zint_render_string));
+ string->next = NULL;
+ string->x = x;
+ string->y = y;
+ string->width = width;
+ string->fsize = fsize;
+ string->length = ustrlen(text);
+ string->text = (unsigned char*) malloc(sizeof (unsigned char) * (ustrlen(text) + 1));
+ ustrcpy(string->text, text);
+
+ if (*last_string)
+ (*last_string)->next = string;
+ else
+ symbol->rendered->strings = string; // First character
+ *last_string = string;
+
+ return 1;
+}
+
+/*
+ * Free the data structures created by render_plot
+ */
+void render_free(struct zint_symbol *symbol) {
+ if (symbol->rendered != NULL) {
+ struct zint_render_line *line;
+ struct zint_render_string *string;
+ struct zint_render_ring *ring;
+ struct zint_render_hexagon *hexagon;
+
+ // Free lines
+ line = symbol->rendered->lines;
+ while (line) {
+ struct zint_render_line *l = line;
+ line = line->next;
+ free(l);
+ }
+ // Free Strings
+ string = symbol->rendered->strings;
+ while (string) {
+ struct zint_render_string *s = string;
+ string = string->next;
+ free(s->text);
+ free(s);
+ }
+
+ // Free Rings
+ ring = symbol->rendered->rings;
+ while (ring) {
+ struct zint_render_ring *r = ring;
+ ring = ring->next;
+ free(r);
+ }
+
+ // Free Hexagons
+ hexagon = symbol->rendered->hexagons;
+ while (hexagon) {
+ struct zint_render_hexagon *h = hexagon;
+ hexagon = hexagon->next;
+ free(h);
+ }
+
+ // Free Render
+ free(symbol->rendered);
+ symbol->rendered = NULL;
+ }
+}
+
+
diff --git a/zint.h b/zint.h
new file mode 100644
index 0000000..41923fb
--- /dev/null
+++ b/zint.h
@@ -0,0 +1,454 @@
+/* zint.h - definitions for libzint */
+/*
+ libzint - the open source barcode library
+ Copyright (C) 2009-2022 Robin Stuart <rstuart114@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the project nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ */
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+/*
+ * For version, see "zintconfig.h"
+ * For documentation, see "../docs/manual.txt"
+ */
+
+#ifndef ZINT_H
+#define ZINT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ struct zint_vector_rect {
+ float x, y, height, width;
+ int colour; /* -1 for foreground, 1-8 for Cyan, Blue, Magenta, Red, Yellow, Green, Black, White */
+ struct zint_vector_rect *next; /* Pointer to next rectangle */
+ };
+
+ struct zint_vector_hexagon {
+ float x, y, diameter;
+ int rotation; /* 0, 90, 180, 270 degrees */
+ struct zint_vector_hexagon *next; /* Pointer to next hexagon */
+ };
+
+ struct zint_vector_string {
+ float x, y; /* x, y position relative to halign */
+ float fsize; /* Font size */
+ float width; /* Suggested string width, may be 0 if none recommended */
+ int length; /* Number of characters */
+ int rotation; /* 0, 90, 180, 270 degrees */
+ int halign; /* Horizontal alignment: 0 for centre, 1 for left, 2 for right (end) */
+ unsigned char *text;
+ struct zint_vector_string *next; /* Pointer to next string */
+ };
+
+ struct zint_vector_circle {
+ float x, y;
+ float diameter; /* Circle diameter. Does not include width (if any) */
+ float width; /* Width of circle perimeter (circumference). 0 for fill (disc) */
+ int colour; /* Non-zero for draw with background colour (else draw with foreground colour) */
+ struct zint_vector_circle *next; /* Pointer to next circle */
+ };
+
+ /* Vector header */
+ struct zint_vector {
+ float width, height; /* Width, height of barcode image (including text, whitespace) */
+ struct zint_vector_rect *rectangles; /* Pointer to first rectangle */
+ struct zint_vector_hexagon *hexagons; /* Pointer to first hexagon */
+ struct zint_vector_string *strings; /* Pointer to first string */
+ struct zint_vector_circle *circles; /* Pointer to first circle */
+ };
+
+ /* Structured Append info - ignored unless `zint_structapp.count` is set to non-zero value */
+ struct zint_structapp {
+ int index; /* Position in Structured Append sequence, 1-based. Must be <= `count` */
+ int count; /* Number of symbols in Structured Append sequence. Set >= 2 to add SA Info */
+ char id[32]; /* Optional ID to distinguish sequence, ASCII, NUL-terminated unless max 32 long */
+ };
+
+ /* Main symbol structure */
+ struct zint_symbol {
+ int symbology; /* Symbol to use (see BARCODE_XXX below) */
+ float height; /* Barcode height in X-dimensions (ignored for fixed-width barcodes) */
+ float scale; /* Scale factor when printing barcode, i.e. adjusts X-dimension. Default 1 */
+ int whitespace_width; /* Width in X-dimensions of whitespace to left & right of barcode */
+ int whitespace_height; /* Height in X-dimensions of whitespace above & below the barcode */
+ int border_width; /* Size of border in X-dimensions */
+ int output_options; /* Various output parameters (bind, box etc, see below) */
+ char fgcolour[10]; /* Foreground as RGB/RGBA hexadecimal string, 6 or 8 characters, NUL-terminated */
+ char bgcolour[10]; /* Background as RGB/RGBA hexadecimal string, 6 or 8 characters, NUL-terminated */
+ char *fgcolor; /* Pointer to fgcolour (alternate spelling) */
+ char *bgcolor; /* Pointer to bgcolour (alternate spelling) */
+ char outfile[256]; /* Name of file to output to, NUL-terminated. Default "out.png" ("out.gif" if NO_PNG) */
+ char primary[128]; /* Primary message data (MaxiCode, Composite), NUL-terminated */
+ int option_1; /* Symbol-specific options (see "../docs/manual.txt") */
+ int option_2; /* Symbol-specific options */
+ int option_3; /* Symbol-specific options */
+ int show_hrt; /* Show (1) or hide (0) Human Readable Text. Default 1 */
+ int fontsize; /* Unused */
+ int input_mode; /* Encoding of input data (see DATA_MODE etc below). Default DATA_MODE */
+ int eci; /* Extended Channel Interpretation. Default 0 (none) */
+ float dot_size; /* Size of dots used in BARCODE_DOTTY_MODE. Default 0.8 */
+ float guard_descent; /* Height in X-dimensions that EAN/UPC guard bars descend. Default 5 */
+ struct zint_structapp structapp; /* Structured Append info. Default structapp.count 0 (none) */
+ int warn_level; /* Affects error/warning value returned by Zint API (see WARN_XXX below) */
+ int debug; /* Debugging flags */
+ unsigned char text[128]; /* Human Readable Text (if any), UTF-8, NUL-terminated (output only) */
+ int rows; /* Number of rows used by the symbol (output only) */
+ int width; /* Width of the generated symbol (output only) */
+ unsigned char encoded_data[200][144]; /* Encoded data (output only). Allows for rows of 1152 modules */
+ float row_height[200]; /* Heights of rows (output only). Allows for 200 row DotCode */
+ char errtxt[100]; /* Error message if an error or warning occurs, NUL-terminated (output only) */
+ unsigned char *bitmap; /* Stored bitmap image (raster output only) */
+ int bitmap_width; /* Width of bitmap image (raster output only) */
+ int bitmap_height; /* Height of bitmap image (raster output only) */
+ unsigned char *alphamap; /* Array of alpha values used (raster output only) */
+ unsigned int bitmap_byte_length; /* Size of BMP bitmap data (raster output only) */
+ struct zint_vector *vector; /* Pointer to vector header (vector output only) */
+ };
+
+ /* Segment for use with `ZBarcode_Encode_Segs()` below */
+ struct zint_seg {
+ unsigned char *source; /* Data to encode */
+ int length; /* Length of `source`. If 0, `source` must be NUL-terminated */
+ int eci; /* Extended Channel Interpretation */
+ };
+
+/* Symbologies (`symbol->symbology`) */
+ /* Tbarcode 7 codes */
+#define BARCODE_CODE11 1 /* Code 11 */
+#define BARCODE_C25STANDARD 2 /* 2 of 5 Standard (Matrix) */
+#define BARCODE_C25MATRIX 2 /* Legacy */
+#define BARCODE_C25INTER 3 /* 2 of 5 Interleaved */
+#define BARCODE_C25IATA 4 /* 2 of 5 IATA */
+#define BARCODE_C25LOGIC 6 /* 2 of 5 Data Logic */
+#define BARCODE_C25IND 7 /* 2 of 5 Industrial */
+#define BARCODE_CODE39 8 /* Code 39 */
+#define BARCODE_EXCODE39 9 /* Extended Code 39 */
+#define BARCODE_EANX 13 /* EAN (European Article Number) */
+#define BARCODE_EANX_CHK 14 /* EAN + Check Digit */
+#define BARCODE_GS1_128 16 /* GS1-128 */
+#define BARCODE_EAN128 16 /* Legacy */
+#define BARCODE_CODABAR 18 /* Codabar */
+#define BARCODE_CODE128 20 /* Code 128 */
+#define BARCODE_DPLEIT 21 /* Deutsche Post Leitcode */
+#define BARCODE_DPIDENT 22 /* Deutsche Post Identcode */
+#define BARCODE_CODE16K 23 /* Code 16k */
+#define BARCODE_CODE49 24 /* Code 49 */
+#define BARCODE_CODE93 25 /* Code 93 */
+#define BARCODE_FLAT 28 /* Flattermarken */
+#define BARCODE_DBAR_OMN 29 /* GS1 DataBar Omnidirectional */
+#define BARCODE_RSS14 29 /* Legacy */
+#define BARCODE_DBAR_LTD 30 /* GS1 DataBar Limited */
+#define BARCODE_RSS_LTD 30 /* Legacy */
+#define BARCODE_DBAR_EXP 31 /* GS1 DataBar Expanded */
+#define BARCODE_RSS_EXP 31 /* Legacy */
+#define BARCODE_TELEPEN 32 /* Telepen Alpha */
+#define BARCODE_UPCA 34 /* UPC-A */
+#define BARCODE_UPCA_CHK 35 /* UPC-A + Check Digit */
+#define BARCODE_UPCE 37 /* UPC-E */
+#define BARCODE_UPCE_CHK 38 /* UPC-E + Check Digit */
+#define BARCODE_POSTNET 40 /* USPS (U.S. Postal Service) POSTNET */
+#define BARCODE_MSI_PLESSEY 47 /* MSI Plessey */
+#define BARCODE_FIM 49 /* Facing Identification Mark */
+#define BARCODE_LOGMARS 50 /* LOGMARS */
+#define BARCODE_PHARMA 51 /* Pharmacode One-Track */
+#define BARCODE_PZN 52 /* Pharmazentralnummer */
+#define BARCODE_PHARMA_TWO 53 /* Pharmacode Two-Track */
+#define BARCODE_CEPNET 54 /* Brazilian CEPNet Postal Code */
+#define BARCODE_PDF417 55 /* PDF417 */
+#define BARCODE_PDF417COMP 56 /* Compact PDF417 (Truncated PDF417) */
+#define BARCODE_PDF417TRUNC 56 /* Legacy */
+#define BARCODE_MAXICODE 57 /* MaxiCode */
+#define BARCODE_QRCODE 58 /* QR Code */
+#define BARCODE_CODE128B 60 /* Code 128 (Subset B) */
+#define BARCODE_AUSPOST 63 /* Australia Post Standard Customer */
+#define BARCODE_AUSREPLY 66 /* Australia Post Reply Paid */
+#define BARCODE_AUSROUTE 67 /* Australia Post Routing */
+#define BARCODE_AUSREDIRECT 68 /* Australia Post Redirection */
+#define BARCODE_ISBNX 69 /* ISBN */
+#define BARCODE_RM4SCC 70 /* Royal Mail 4-State Customer Code */
+#define BARCODE_DATAMATRIX 71 /* Data Matrix (ECC200) */
+#define BARCODE_EAN14 72 /* EAN-14 */
+#define BARCODE_VIN 73 /* Vehicle Identification Number */
+#define BARCODE_CODABLOCKF 74 /* Codablock-F */
+#define BARCODE_NVE18 75 /* NVE-18 (SSCC-18) */
+#define BARCODE_JAPANPOST 76 /* Japanese Postal Code */
+#define BARCODE_KOREAPOST 77 /* Korea Post */
+#define BARCODE_DBAR_STK 79 /* GS1 DataBar Stacked */
+#define BARCODE_RSS14STACK 79 /* Legacy */
+#define BARCODE_DBAR_OMNSTK 80 /* GS1 DataBar Stacked Omnidirectional */
+#define BARCODE_RSS14STACK_OMNI 80 /* Legacy */
+#define BARCODE_DBAR_EXPSTK 81 /* GS1 DataBar Expanded Stacked */
+#define BARCODE_RSS_EXPSTACK 81 /* Legacy */
+#define BARCODE_PLANET 82 /* USPS PLANET */
+#define BARCODE_MICROPDF417 84 /* MicroPDF417 */
+#define BARCODE_USPS_IMAIL 85 /* USPS Intelligent Mail (OneCode) */
+#define BARCODE_ONECODE 85 /* Legacy */
+#define BARCODE_PLESSEY 86 /* UK Plessey */
+
+ /* Tbarcode 8 codes */
+#define BARCODE_TELEPEN_NUM 87 /* Telepen Numeric */
+#define BARCODE_ITF14 89 /* ITF-14 */
+#define BARCODE_KIX 90 /* Dutch Post KIX Code */
+#define BARCODE_AZTEC 92 /* Aztec Code */
+#define BARCODE_DAFT 93 /* DAFT Code */
+#define BARCODE_DPD 96 /* DPD Code */
+#define BARCODE_MICROQR 97 /* Micro QR Code */
+
+ /* Tbarcode 9 codes */
+#define BARCODE_HIBC_128 98 /* HIBC (Health Industry Barcode) Code 128 */
+#define BARCODE_HIBC_39 99 /* HIBC Code 39 */
+#define BARCODE_HIBC_DM 102 /* HIBC Data Matrix */
+#define BARCODE_HIBC_QR 104 /* HIBC QR Code */
+#define BARCODE_HIBC_PDF 106 /* HIBC PDF417 */
+#define BARCODE_HIBC_MICPDF 108 /* HIBC MicroPDF417 */
+#define BARCODE_HIBC_BLOCKF 110 /* HIBC Codablock-F */
+#define BARCODE_HIBC_AZTEC 112 /* HIBC Aztec Code */
+
+ /* Tbarcode 10 codes */
+#define BARCODE_DOTCODE 115 /* DotCode */
+#define BARCODE_HANXIN 116 /* Han Xin (Chinese Sensible) Code */
+
+ /* Tbarcode 11 codes */
+#define BARCODE_MAILMARK 121 /* Royal Mail 4-State Mailmark */
+
+ /* Zint specific */
+#define BARCODE_AZRUNE 128 /* Aztec Runes */
+#define BARCODE_CODE32 129 /* Code 32 */
+#define BARCODE_EANX_CC 130 /* EAN Composite */
+#define BARCODE_GS1_128_CC 131 /* GS1-128 Composite */
+#define BARCODE_EAN128_CC 131 /* Legacy */
+#define BARCODE_DBAR_OMN_CC 132 /* GS1 DataBar Omnidirectional Composite */
+#define BARCODE_RSS14_CC 132 /* Legacy */
+#define BARCODE_DBAR_LTD_CC 133 /* GS1 DataBar Limited Composite */
+#define BARCODE_RSS_LTD_CC 133 /* Legacy */
+#define BARCODE_DBAR_EXP_CC 134 /* GS1 DataBar Expanded Composite */
+#define BARCODE_RSS_EXP_CC 134 /* Legacy */
+#define BARCODE_UPCA_CC 135 /* UPC-A Composite */
+#define BARCODE_UPCE_CC 136 /* UPC-E Composite */
+#define BARCODE_DBAR_STK_CC 137 /* GS1 DataBar Stacked Composite */
+#define BARCODE_RSS14STACK_CC 137 /* Legacy */
+#define BARCODE_DBAR_OMNSTK_CC 138 /* GS1 DataBar Stacked Omnidirectional Composite */
+#define BARCODE_RSS14_OMNI_CC 138 /* Legacy */
+#define BARCODE_DBAR_EXPSTK_CC 139 /* GS1 DataBar Expanded Stacked Composite */
+#define BARCODE_RSS_EXPSTACK_CC 139 /* Legacy */
+#define BARCODE_CHANNEL 140 /* Channel Code */
+#define BARCODE_CODEONE 141 /* Code One */
+#define BARCODE_GRIDMATRIX 142 /* Grid Matrix */
+#define BARCODE_UPNQR 143 /* UPNQR (Univerzalnega Plačilnega Naloga QR) */
+#define BARCODE_ULTRA 144 /* Ultracode */
+#define BARCODE_RMQR 145 /* Rectangular Micro QR Code (rMQR) */
+#define BARCODE_BC412 146 /* IBM BC412 (SEMI T1-95) */
+#define BARCODE_LAST 146 /* Max barcode number marker, not barcode */
+
+/* Output options (`symbol->output_options`) */
+#define BARCODE_NO_ASCII 0x0001 /* Legacy (no-op) */
+#define BARCODE_BIND 0x0002 /* Boundary bars above & below the symbol and between stacked symbols */
+#define BARCODE_BOX 0x0004 /* Box around symbol */
+#define BARCODE_STDOUT 0x0008 /* Output to stdout */
+#define READER_INIT 0x0010 /* Reader Initialisation (Programming) */
+#define SMALL_TEXT 0x0020 /* Use smaller font */
+#define BOLD_TEXT 0x0040 /* Use bold font */
+#define CMYK_COLOUR 0x0080 /* CMYK colour space (Encapsulated PostScript and TIF) */
+#define BARCODE_DOTTY_MODE 0x0100 /* Plot a matrix symbol using dots rather than squares */
+#define GS1_GS_SEPARATOR 0x0200 /* Use GS instead of FNC1 as GS1 separator (Data Matrix) */
+#define OUT_BUFFER_INTERMEDIATE 0x0400 /* Return ASCII values in bitmap buffer (OUT_BUFFER only) */
+#define BARCODE_QUIET_ZONES 0x0800 /* Add compliant quiet zones (additional to any specified whitespace) */
+ /* Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones
+ */
+#define BARCODE_NO_QUIET_ZONES 0x1000 /* Disable quiet zones, notably those with defaults as listed above */
+#define COMPLIANT_HEIGHT 0x2000 /* Warn if height not compliant and use standard height (if any) as default */
+
+/* Input data types (`symbol->input_mode`) */
+#define DATA_MODE 0 /* Binary */
+#define UNICODE_MODE 1 /* UTF-8 */
+#define GS1_MODE 2 /* GS1 */
+/* The following may be OR-ed with above */
+#define ESCAPE_MODE 0x0008 /* Process escape sequences */
+#define GS1PARENS_MODE 0x0010 /* Process parentheses as GS1 AI delimiters (instead of square brackets) */
+#define GS1NOCHECK_MODE 0x0020 /* Do not check validity of GS1 data (except that printable ASCII only) */
+#define HEIGHTPERROW_MODE 0x0040 /* Interpret `height` as per-row rather than as overall height */
+#define FAST_MODE 0x0080 /* Use faster if less optimal encodation for symbologies that support it */
+ /* Note: only DATAMATRIX currently */
+
+/* Data Matrix specific options (`symbol->option_3`) */
+#define DM_SQUARE 100 /* Only consider square versions on automatic symbol size selection */
+#define DM_DMRE 101 /* Consider DMRE versions on automatic symbol size selection */
+
+/* QR, Han Xin, Grid Matrix specific options (`symbol->option_3`) */
+#define ZINT_FULL_MULTIBYTE 200 /* Enable Kanji/Hanzi compression for Latin-1 & binary data */
+
+/* Ultracode specific option (`symbol->option_3`) */
+#define ULTRA_COMPRESSION 128 /* Enable Ultracode compression (experimental) */
+
+/* Warning and error conditions (API return values) */
+#define ZINT_WARN_INVALID_OPTION 2 /* Invalid option given but overridden by Zint */
+#define ZINT_WARN_USES_ECI 3 /* Automatic ECI inserted by Zint */
+#define ZINT_WARN_NONCOMPLIANT 4 /* Symbol created not compliant with standards */
+#define ZINT_ERROR 5 /* Warn/error marker, not returned */
+#define ZINT_ERROR_TOO_LONG 5 /* Input data wrong length */
+#define ZINT_ERROR_INVALID_DATA 6 /* Input data incorrect */
+#define ZINT_ERROR_INVALID_CHECK 7 /* Input check digit incorrect */
+#define ZINT_ERROR_INVALID_OPTION 8 /* Incorrect option given */
+#define ZINT_ERROR_ENCODING_PROBLEM 9 /* Internal error (should not happen) */
+#define ZINT_ERROR_FILE_ACCESS 10 /* Error opening output file */
+#define ZINT_ERROR_MEMORY 11 /* Memory allocation (malloc) failure */
+#define ZINT_ERROR_FILE_WRITE 12 /* Error writing to output file */
+#define ZINT_ERROR_USES_ECI 13 /* Error counterpart of warning if WARN_FAIL_ALL set (see below) */
+#define ZINT_ERROR_NONCOMPLIANT 14 /* Error counterpart of warning if WARN_FAIL_ALL set */
+
+/* Warning warn (`symbol->warn_level`) */
+#define WARN_DEFAULT 0 /* Default behaviour */
+#define WARN_FAIL_ALL 2 /* Treat warning as error */
+
+/* Capability flags (ZBarcode_Cap() `cap_flag`) */
+#define ZINT_CAP_HRT 0x0001 /* Prints Human Readable Text? */
+#define ZINT_CAP_STACKABLE 0x0002 /* Is stackable? */
+#define ZINT_CAP_EXTENDABLE 0x0004 /* Is extendable with add-on data? (Is EAN/UPC?) */
+#define ZINT_CAP_COMPOSITE 0x0008 /* Can have composite data? */
+#define ZINT_CAP_ECI 0x0010 /* Supports Extended Channel Interpretations? */
+#define ZINT_CAP_GS1 0x0020 /* Supports GS1 data? */
+#define ZINT_CAP_DOTTY 0x0040 /* Can be output as dots? */
+#define ZINT_CAP_QUIET_ZONES 0x0080 /* Has default quiet zones? */
+#define ZINT_CAP_FIXED_RATIO 0x0100 /* Has fixed width-to-height (aspect) ratio? */
+#define ZINT_CAP_READER_INIT 0x0200 /* Supports Reader Initialisation? */
+#define ZINT_CAP_FULL_MULTIBYTE 0x0400 /* Supports full-multibyte option? */
+#define ZINT_CAP_MASK 0x0800 /* Is mask selectable? */
+#define ZINT_CAP_STRUCTAPP 0x1000 /* Supports Structured Append? */
+#define ZINT_CAP_COMPLIANT_HEIGHT 0x2000 /* Has compliant height? */
+
+/* The largest amount of data that can be encoded is 4350 4-byte UTF-8 chars in Han Xin Code */
+#define ZINT_MAX_DATA_LEN 17400
+/* Maximum number of segments allowed for (`seg_count`) */
+#define ZINT_MAX_SEG_COUNT 256
+
+/* Debug flags (`symbol->debug`) */
+#define ZINT_DEBUG_PRINT 0x0001 /* Print debug info (if any) to stdout */
+#define ZINT_DEBUG_TEST 0x0002 /* For internal test use only */
+
+#ifdef _WIN32
+# if defined(DLL_EXPORT) || defined(PIC) || defined(_USRDLL)
+# define ZINT_EXTERN __declspec(dllexport)
+# elif defined(ZINT_DLL)
+# define ZINT_EXTERN __declspec(dllimport)
+# else
+# define ZINT_EXTERN extern
+# endif
+#else
+# define ZINT_EXTERN extern
+#endif
+
+ /* Create and initialize a symbol structure */
+ ZINT_EXTERN struct zint_symbol *ZBarcode_Create(void);
+
+ /* Free any output buffers that may have been created and initialize output fields */
+ ZINT_EXTERN void ZBarcode_Clear(struct zint_symbol *symbol);
+
+ /* Free a symbol structure, including any output buffers */
+ ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol);
+
+
+ /* Encode a barcode. If `length` is 0, `source` must be NUL-terminated */
+ ZINT_EXTERN int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length);
+
+ /* Encode a barcode with multiple ECI segments */
+ ZINT_EXTERN int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count);
+
+ /* Encode a barcode using input data from file `filename` */
+ ZINT_EXTERN int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename);
+
+ /* Output a previously encoded symbol to file `symbol->outfile` */
+ ZINT_EXTERN int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle);
+
+
+ /* Encode and output a symbol to file `symbol->outfile` */
+ ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *source, int length,
+ int rotate_angle);
+
+ /* Encode a symbol with multiple ECI segments and output to file `symbol->outfile` */
+ ZINT_EXTERN int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count, int rotate_angle);
+
+ /* Encode a symbol using input data from file `filename` and output to file `symbol->outfile` */
+ ZINT_EXTERN int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, const char *filename,
+ int rotate_angle);
+
+ /* Plot to gLabels - backported from 2.6.7 by brozkeff 2022-11-25 */
+ ZINT_EXTERN int ZBarcode_Render(struct zint_symbol *symbol, const float width, const float height);
+
+ /* Output a previously encoded symbol to memory as raster (`symbol->bitmap`) */
+ ZINT_EXTERN int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle);
+
+ /* Encode and output a symbol to memory as raster (`symbol->bitmap`) */
+ ZINT_EXTERN int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *source, int length,
+ int rotate_angle);
+
+ /* Encode a symbol with multiple ECI segments and output to memory as raster (`symbol->bitmap`) */
+ ZINT_EXTERN int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count, int rotate_angle);
+
+ /* Encode a symbol using input data from file `filename` and output to memory as raster (`symbol->bitmap`) */
+ ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, const char *filename,
+ int rotate_angle);
+
+
+ /* Output a previously encoded symbol to memory as vector (`symbol->vector`) */
+ ZINT_EXTERN int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle);
+
+ /* Encode and output a symbol to memory as vector (`symbol->vector`) */
+ ZINT_EXTERN int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, const unsigned char *source,
+ int length, int rotate_angle);
+
+ /* Encode a symbol with multiple ECI segments and output to memory as vector (`symbol->vector`) */
+ ZINT_EXTERN int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, const struct zint_seg segs[],
+ const int seg_count, int rotate_angle);
+
+ /* Encode a symbol using input data from file `filename` and output to memory as vector (`symbol->vector`) */
+ ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const char *filename,
+ int rotate_angle);
+
+
+ /* Is `symbol_id` a recognized symbology? */
+ ZINT_EXTERN int ZBarcode_ValidID(int symbol_id);
+
+ /* Copy BARCODE_XXX name of `symbol_id` into `name` buffer, NUL-terminated.
+ Returns 0 if valid, non-zero (1 or -1) if not valid */
+ ZINT_EXTERN int ZBarcode_BarcodeName(int symbol_id, char name[32]);
+
+ /* Return the capability flags for symbology `symbol_id` that match `cap_flag` */
+ ZINT_EXTERN unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag);
+
+ /* Return the version of Zint linked to */
+ ZINT_EXTERN int ZBarcode_Version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/* vim: set ts=4 sw=4 et : */
+#endif /* ZINT_H */
--
2.17.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment