Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE,

GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA
RMQR: fix ECI encoding (wrong bit length for indicator)
MICROQR: check versions M1 and M2 for allowed characters so as to give
  better error messages
DOTCODE: some small optimizations
common.c: add is_chr(), segs_length(), segs_cpy()
CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add
  namespace prefixes to static funcs/data
includes: use Z_ prefix, unuse double underscore prefixes (guard defines)
manual.txt: compress some tables using double/treble column sets
This commit is contained in:
gitlost 2022-05-09 19:50:50 +01:00
parent 3b9d989894
commit f58c80e290
81 changed files with 12026 additions and 4701 deletions

View file

@ -1,7 +1,7 @@
/* library.c - external functions of libzint
libzint - the open source barcode library
Copyright (C) 2009 - 2021 Robin Stuart <rstuart114@gmail.com>
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
@ -28,7 +28,6 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* vim: set ts=4 sw=4 et : */
#include <assert.h>
#include <errno.h>
@ -162,15 +161,15 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int
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, unsigned char source[], int length); /* PDF417 */
INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int length); /* Micro PDF417 */
INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int length); /* Maxicode */
INTERNAL int dbar_omn(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS-14 */
INTERNAL int dbar_ltd(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Limited */
INTERNAL int dbar_exp(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */
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, unsigned char source[], int length); /* Aztec 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 */
@ -181,20 +180,21 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l
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, unsigned char source[], int length); /* Code One */
INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Grid Matrix */
INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int length); /* Han Xin */
INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int length); /* DotCode */
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, unsigned char source[], int length); /* QR Code */
INTERNAL int datamatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Data Matrix (IEC16022) */
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, unsigned char source[], int length); /* Ultracode */
INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length); /* rMQR */
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 plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
@ -289,7 +289,10 @@ static int dump_plot(struct zint_symbol *symbol) {
static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */
/* Process health industry bar code data */
static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) {
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];
@ -317,45 +320,48 @@ static int hibc(struct zint_symbol *symbol, unsigned char source[], int 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, (unsigned char *) to_process, length);
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, (unsigned char *) to_process, length);
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, (unsigned char *) to_process, length);
error_number = datamatrix(symbol, segs, seg_count);
break;
case BARCODE_HIBC_QR:
error_number = qrcode(symbol, (unsigned char *) to_process, length);
error_number = qrcode(symbol, segs, seg_count);
break;
case BARCODE_HIBC_PDF:
error_number = pdf417(symbol, (unsigned char *) to_process, length);
error_number = pdf417(symbol, segs, seg_count);
break;
case BARCODE_HIBC_MICPDF:
error_number = micropdf417(symbol, (unsigned char *) to_process, length);
error_number = micropdf417(symbol, segs, seg_count);
break;
case BARCODE_HIBC_AZTEC:
error_number = aztec(symbol, (unsigned char *) to_process, length);
error_number = aztec(symbol, segs, seg_count);
break;
case BARCODE_HIBC_BLOCKF:
error_number = codablockf(symbol, (unsigned char *) to_process, length);
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) {
/* Returns 1 if symbology MUST have GS1 data */
switch (symbology) {
case BARCODE_GS1_128:
@ -370,8 +376,8 @@ static int check_force_gs1(const int symbology) {
return is_composite(symbology);
}
/* Returns 1 if symbology supports GS1 data */
static int gs1_compliant(const int symbology) {
/* Returns 1 if symbology supports GS1 data */
switch (symbology) {
case BARCODE_CODE16K:
@ -393,8 +399,8 @@ static int gs1_compliant(const int symbology) {
return check_force_gs1(symbology);
}
/* Returns 1 if symbology can encode the ECI character */
static int supports_eci(const int symbology) {
/* Returns 1 if symbology can encode the ECI character */
switch (symbology) {
case BARCODE_AZTEC:
@ -417,8 +423,27 @@ static int supports_eci(const int symbology) {
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) {
/* Returns 1 if symbology supports HRT */
if (is_fixed_ratio(symbology)) {
return 0;
@ -463,9 +488,16 @@ static int has_hrt(const int symbology) {
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_func_t)(struct zint_symbol *, unsigned char *, int);
static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = {
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*/
@ -498,22 +530,26 @@ static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = {
rmqr,
};
static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int length);
static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count);
static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char *source, const int length) {
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 */
/* These are the "elite" standards which have support for specific character sets + ECI */
case BARCODE_QRCODE:
case BARCODE_MICROQR:
case BARCODE_GRIDMATRIX:
case BARCODE_HANXIN:
case BARCODE_UPNQR:
case BARCODE_RMQR:
error_number = (*barcode_funcs[symbol->symbology])(symbol, source, length);
error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, segs, seg_count);
break;
default: error_number = reduced_charset(symbol, source, length);
/* 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;
}
@ -521,36 +557,69 @@ static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char
}
/* 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, unsigned char *source, int length) {
static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
int error_number = 0;
unsigned char *preprocessed = source;
int i;
const int eci_length = get_eci_length(symbol->eci, source, length);
#ifndef _MSC_VER
unsigned char preprocessed_buf[eci_length + 1];
struct zint_seg local_segs[seg_count];
int convertible[seg_count];
#else
unsigned char *preprocessed_buf = (unsigned char *) _alloca(eci_length + 1);
struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count);
int *convertible = (int *) _alloca(sizeof(int) * seg_count);
#endif
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);
#ifndef _MSC_VER
unsigned char preprocessed_buf[eci_length_segs + seg_count];
#else
unsigned char *preprocessed_buf = (unsigned char *) _alloca(eci_length_segs + seg_count);
#endif
if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible(symbol->eci)) {
/* Prior check ensures ECI only set for those that support it */
segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */
preprocessed = preprocessed_buf;
error_number = utf8_to_eci(symbol->eci, source, preprocessed, &length);
if (error_number != 0) {
if (symbol->eci) {
sprintf(symbol->errtxt, "244: Invalid character in input data for ECI %d", symbol->eci);
} else {
strcpy(symbol->errtxt, "204: Invalid character in input data (ISO/IEC 8859-1 only)");
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;
}
return error_number;
}
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(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);
}
}
error_number = (*barcode_funcs[symbol->symbology])(symbol, preprocessed, length);
return error_number;
}
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length) {
int i;
@ -693,38 +762,93 @@ STATIC_UNLESS_ZINT_TEST int escape_char_process(struct zint_symbol *symbol, unsi
/* 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) {
int error_number, warn_number;
#ifdef _MSC_VER
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;
#ifndef _MSC_VER
struct zint_seg local_segs[seg_count > 0 ? seg_count : 1];
#else
struct zint_seg *local_segs;
unsigned char *local_sources;
local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * (seg_count > 0 ? seg_count : 1));
#endif
if (!symbol) return ZINT_ERROR_INVALID_DATA;
if (segs == NULL) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "200: Input segments NULL");
}
if (seg_count <= 0) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "205: Input segment count 0");
}
if (seg_count > ZINT_MAX_SEG_COUNT) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "771: Too many input segments (max 256)");
}
/* 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) {
sprintf(symbol->errtxt, "773: Input segment %d length zero", 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 (symbol->debug & ZINT_DEBUG_PRINT) {
printf("ZBarcode_Encode: symbology: %d, input_mode: 0x%X, ECI: %d, option_1: %d, option_2: %d,"
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,"
" length: %d, First 10 source: \"%.*s\", First 10 primary: \"%.10s\"\n",
" 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,
length, length < 10 ? length : 10, source ? (const char *) source : "<NULL>", symbol->primary);
seg_count, local_segs[0].length, local_segs[0].length < 10 ? local_segs[0].length : 10,
local_segs[0].source, symbol->primary);
}
warn_number = 0;
if (source == NULL) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "200: Input data NULL");
}
if (length <= 0) {
length = (int) ustrlen(source);
}
if (length <= 0) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "205: No input data");
}
if (length > ZINT_MAX_DATA_LEN) {
if (total_len > ZINT_MAX_DATA_LEN) {
return error_tag(symbol, ZINT_ERROR_TOO_LONG, "243: Input data too long");
}
/* First check the symbology field */
/* 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) {
@ -835,15 +959,27 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
}
}
if (symbol->eci != 0) {
if (!(supports_eci(symbol->symbology))) {
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "217: Symbology does not support ECI switching");
}
if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) {
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "218: Invalid ECI mode");
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)");
}
@ -875,29 +1011,50 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
symbol->input_mode = DATA_MODE; /* Reset completely TODO: in future, warn/error */
}
if ((symbol->input_mode & 0x07) == UNICODE_MODE && !is_valid_utf8(source, length)) {
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "245: Invalid UTF-8 in input data");
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");
}
#ifndef _MSC_VER
unsigned char local_source[length + 1];
#else
local_source = (unsigned char *) _alloca(length + 1);
#endif
memcpy(local_source, source, length);
local_source[length] = '\0';
/* Start acting on input mode */
if (symbol->input_mode & ESCAPE_MODE) {
error_number = escape_char_process(symbol, local_source, &length); /* Only returns errors, not warnings */
if (error_number != 0) {
return error_tag(symbol, error_number, NULL);
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) {
strip_bom(local_source, &length);
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");
}
}
}
#ifndef _MSC_VER
unsigned char local_sources[total_len + seg_count];
#else
local_sources = (unsigned char *) _alloca(total_len + seg_count);
#endif
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->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))) {
@ -906,11 +1063,11 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
// handle it themselves
if (is_composite(symbol->symbology) || !check_force_gs1(symbol->symbology)) {
#ifndef _MSC_VER
unsigned char reduced[length + 1];
unsigned char reduced[local_segs[0].length + 1];
#else
unsigned char *reduced = (unsigned char *) _alloca(length + 1);
unsigned char *reduced = (unsigned char *) _alloca(local_segs[0].length + 1);
#endif
error_number = gs1_verify(symbol, local_source, length, reduced);
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)
@ -923,29 +1080,29 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
}
warn_number = error_number; /* Override any previous warning (errtxt has been overwritten) */
}
ustrcpy(local_source, reduced); // Cannot contain NUL char
length = (int) ustrlen(local_source);
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_source, length);
error_number = extended_or_reduced_charset(symbol, local_segs, seg_count);
if ((error_number == ZINT_ERROR_INVALID_DATA) && symbol->eci == 0 && supports_eci(symbol->symbology)
if ((error_number == ZINT_ERROR_INVALID_DATA) && have_zero_eci && supports_eci(symbol->symbology)
&& (symbol->input_mode & 0x07) == UNICODE_MODE) {
/* Try another ECI mode */
symbol->eci = get_best_eci(local_source, length);
if (symbol->eci != 0) {
error_number = extended_or_reduced_charset(symbol, local_source, length);
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", symbol->eci);
sprintf(symbol->errtxt, "222: Encoded data includes ECI %d", first_eci_set);
}
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", symbol->eci);
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", first_eci_set);
}
}
}
@ -1069,10 +1226,24 @@ int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) {
/* 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(symbol, source, length);
error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
if (error_number >= ZINT_ERROR) {
return error_number;
}
@ -1088,10 +1259,24 @@ int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *s
/* 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(symbol, source, length);
error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
if (error_number >= ZINT_ERROR) {
return error_number;
}
@ -1108,10 +1293,24 @@ int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *
/* 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(symbol, source, length);
error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count);
if (error_number >= ZINT_ERROR) {
return error_number;
}
@ -1601,3 +1800,5 @@ int ZBarcode_Version(void) {
}
return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE;
}
/* vim: set ts=4 sw=4 et : */