diff --git a/ChangeLog b/ChangeLog
index 943b50fe..74b1a673 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@ Version 2.13.0.9 (dev) not released yet
- New `memfile` & `memfile_size` fields in `symbol` for use with new output
option `BARCODE_MEMORY_FILE`
- Invalid `input_mode` now returns warning
+- New CODE128-only special extra escape `\^1` for manually inserting FNC1s
Changes
-------
@@ -21,6 +22,8 @@ Changes
iso4217: new ISO 4217 currency code 924
- AZTEC: workaround MSVC 2022 optimizer bug in `az_populate_map()` loops,
ticket #317, props Andre Maute
+- CODE128: Add new extra escape `\^1` for manual insertion of FNC1s, ticket
+ #324, props Jim Shank
Bugs
----
diff --git a/README.clang-tidy b/README.clang-tidy
index 1d16ecec..55be6fc9 100644
--- a/README.clang-tidy
+++ b/README.clang-tidy
@@ -1,16 +1,16 @@
-% README.clang-tidy 2024-03-03
-% Current as of latest clang-tidy-19 from Ubuntu 22.04 apt package
+% README.clang-tidy 2024-09-03
+% Current as of latest clang-tidy-20 from Ubuntu 22.04 apt package
Requires cmake in "build" sub-directory with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (for "build/compile_commands.json")
and -DCMAKE_BUILD_TYPE=Debug (so `assert()`s defined), and then make (for Qt generated includes).
In project root directory (warning, slow):
-clang-tidy-19 backend/*.c frontend/*.c backend_qt/*.cpp frontend_qt/*.cpp -p build/compile_commands.json
+clang-tidy-20 backend/*.c frontend/*.c backend_qt/*.cpp frontend_qt/*.cpp -p build/compile_commands.json
For "backend_tcl", which has no "compile_commands.json", specify the tcl include directory, e.g.
-clang-tidy-19 backend_tcl/*.c -- -I/usr/include/tcl8.6
+clang-tidy-20 backend_tcl/*.c -- -I/usr/include/tcl8.6
Options are in ".clang-tidy" (in the project root directory). The excluded checks are
`clang-analyzer-security.insecureAPI.strcpy` (for `strcpy()`, `strcat()` etc), and
@@ -18,5 +18,5 @@ Options are in ".clang-tidy" (in the project root directory). The excluded check
The test suite (cmake given -DZINT_TEST=ON) can also be analysed with an additional check disabled:
-clang-tidy-19 backend/tests/*.c frontend/tests/*.c backend_qt/tests/*.cpp \
+clang-tidy-20 backend/tests/*.c frontend/tests/*.c backend_qt/tests/*.cpp \
-checks='-clang-analyzer-optin.performance.Padding' -p build/compile_commands.json
diff --git a/backend/code128.c b/backend/code128.c
index f2c9027d..1a18249f 100644
--- a/backend/code128.c
+++ b/backend/code128.c
@@ -76,11 +76,11 @@ INTERNAL_DATA const char C128Table[107][6] = { /* Used by CODABLOCKF and CODE16K
};
/* Determine appropriate mode for a given character */
-INTERNAL int c128_parunmodd(const unsigned char llyth) {
+INTERNAL int c128_parunmodd(const unsigned char llyth, const int check_fnc1) {
int modd;
if (llyth <= 31) {
- modd = C128_SHIFTA;
+ modd = check_fnc1 && llyth == '\x1D' ? C128_ABORC : C128_SHIFTA;
} else if ((llyth >= 48) && (llyth <= 57)) {
modd = C128_ABORC;
} else if (llyth <= 95) {
@@ -244,7 +244,7 @@ INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *p_indexliste, const char
*/
INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars) {
- if (source > 127) {
+ if (source >= 128) {
if (source < 160) {
values[(*bar_chars)] = (source - 128) + 64;
} else {
@@ -290,7 +290,7 @@ INTERNAL void c128_set_c(const unsigned char source_a, const unsigned char sourc
(*bar_chars)++;
}
-/* Put set data into set[]. If source given (GS1_MODE) then resolves odd C blocks */
+/* Put set data into set[]. If source given (GS1_MODE or manual FNC1s) then resolves odd C blocks */
INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char set[C128_MAX],
const unsigned char *source) {
int read = 0;
@@ -303,12 +303,13 @@ INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char
}
if (source) {
/* Watch out for odd-length Mode C blocks */
- int c_count = 0;
+ int c_count = 0, have_nonc = 0;
for (i = 0; i < read; i++) {
if (set[i] == 'C') {
if (source[i] == '\x1D') {
if (c_count & 1) {
- if ((i - c_count) != 0) {
+ have_nonc = 1;
+ if (i > c_count) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
@@ -319,8 +320,9 @@ INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char
c_count++;
}
} else {
+ have_nonc = 1;
if (c_count & 1) {
- if ((i - c_count) != 0) {
+ if (i > c_count) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
@@ -330,17 +332,26 @@ INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char
}
}
if (c_count & 1) {
- if ((i - c_count) != 0) {
+ if (i > c_count && have_nonc) {
set[i - c_count] = 'B';
+ if (c_count < 4) {
+ /* Rule 1b */
+ for (j = i - c_count + 1; j < i; j++) {
+ set[j] = 'B';
+ }
+ }
} else {
set[i - 1] = 'B';
}
}
for (i = 1; i < read - 1; i++) {
- if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
- set[i] = 'B';
+ if (set[i] == 'C' && set[i - 1] != 'C' && set[i + 1] != 'C') {
+ set[i] = set[i + 1];
}
}
+ if (read > 1 && set[read - 1] == 'C' && set[read - 2] != 'C') {
+ set[read - 1] = set[read - 2];
+ }
}
}
@@ -351,8 +362,10 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
unsigned char src_buf[C128_MAX + 1];
unsigned char *src = source;
char manual_set[C128_MAX] = {0};
+ unsigned char fncs[C128_MAX] = {0}; /* Manual FNC1 positions */
int list[2][C128_MAX] = {{0}};
char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set = ' ';
+ int have_fnc1 = 0; /* Whether have at least 1 manual FNC1 */
int glyph_count = 0; /* Codeword estimate times 2 */
char dest[1000];
char *d = dest;
@@ -373,16 +386,22 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
j = 0;
for (i = 0; i < length; i++) {
if (source[i] == '\\' && i + 2 < length && source[i + 1] == '^'
- && ((source[i + 2] >= 'A' && source[i + 2] <= 'C') || source[i + 2] == '^')) {
- if (source[i + 2] != '^') {
- i += 2;
- manual_ch = source[i];
- } else { /* Escape sequence '\^^' */
+ && ((source[i + 2] >= 'A' && source[i + 2] <= 'C') || source[i + 2] == '1'
+ || source[i + 2] == '^')) {
+ if (source[i + 2] == '^') { /* Escape sequence '\^^' */
manual_set[j] = manual_ch;
src_buf[j++] = source[i++];
manual_set[j] = manual_ch;
src_buf[j++] = source[i++];
/* Drop second '^' */
+ } else if (source[i + 2] == '1') { /* FNC1 */
+ i += 2;
+ fncs[j] = have_fnc1 = 1;
+ manual_set[j] = manual_ch;
+ src_buf[j++] = '\x1D'; /* Manual FNC1 dummy */
+ } else { /* Manual mode A/B/C */
+ i += 2;
+ manual_ch = source[i];
}
} else {
manual_set[j] = manual_ch;
@@ -456,10 +475,10 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
indexliste = 0;
indexchaine = 0;
- mode = c128_parunmodd(src[indexchaine]);
+ mode = c128_parunmodd(src[indexchaine], fncs[indexchaine]);
if (mode == C128_ABORC
&& (symbol->symbology == BARCODE_CODE128AB
- || (manual_set[indexchaine] == 'A' || manual_set[indexchaine] == 'B'))) {
+ || manual_set[indexchaine] == 'A' || manual_set[indexchaine] == 'B')) {
mode = C128_AORB;
}
@@ -471,10 +490,10 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
if (indexchaine == length) {
break;
}
- mode = c128_parunmodd(src[indexchaine]);
+ mode = c128_parunmodd(src[indexchaine], fncs[indexchaine]);
if (mode == C128_ABORC
&& (symbol->symbology == BARCODE_CODE128AB
- || (manual_set[indexchaine] == 'A' || manual_set[indexchaine] == 'B'))) {
+ || manual_set[indexchaine] == 'A' || manual_set[indexchaine] == 'B')) {
mode = C128_AORB;
}
if (manual_set[indexchaine] != manual_set[indexchaine - 1]) {
@@ -494,29 +513,32 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
}
c128_dxsmooth(list, &indexliste, src == src_buf ? manual_set : NULL);
- /* Resolve odd length C128_LATCHC blocks */
- if ((list[1][0] == C128_LATCHC) && (list[0][0] & 1)) {
- /* Rule 2 */
- list[0][1]++;
- list[0][0]--;
- if (indexliste == 1) {
- list[0][1] = 1;
- list[1][1] = C128_LATCHB;
- indexliste = 2;
+ if (!have_fnc1) {
+ /* Resolve odd length C128_LATCHC blocks */
+ if ((list[1][0] == C128_LATCHC) && (list[0][0] & 1)) {
+ /* Rule 2 */
+ list[0][1]++;
+ list[0][0]--;
+ if (indexliste == 1) {
+ list[0][1] = 1;
+ list[1][1] = C128_LATCHB;
+ indexliste = 2;
+ }
}
- }
- if (indexliste > 1) {
- for (i = 1; i < indexliste; i++) {
- if ((list[1][i] == C128_LATCHC) && (list[0][i] & 1)) {
- /* Rule 3b */
- list[0][i - 1]++;
- list[0][i]--;
+ if (indexliste > 1) {
+ for (i = 1; i < indexliste; i++) {
+ if ((list[1][i] == C128_LATCHC) && (list[0][i] & 1)) {
+ /* Rule 3b */
+ list[0][i - 1]++;
+ list[0][i]--;
+ }
}
}
}
- /* Put set data into set[]. Giving NULL as source as used to resolve odd C blocks which has been done above */
- c128_put_in_set(list, indexliste, set, NULL /*source*/);
+ /* Put set data into set[]. Give NULL as source if no manual FNC1s as used to resolve odd C blocks
+ which has been done above */
+ c128_put_in_set(list, indexliste, set, have_fnc1 ? src : NULL);
if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data: %.*s (%d)\n", length, src, length);
@@ -547,13 +569,12 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
} else {
if ((fset[i] == 'F') && (fset[i - 1] != 'F')) {
glyph_count += 4;
- }
- if ((fset[i] != 'F') && (fset[i - 1] == 'F')) {
+ } else if ((fset[i] != 'F') && (fset[i - 1] == 'F')) {
glyph_count += 4;
}
}
- if (set[i] == 'C') {
+ if (set[i] == 'C' && !fncs[i]) {
glyph_count += 1; /* Half a codeword */
} else {
glyph_count += 2;
@@ -622,25 +643,25 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
read = 0;
do {
- if ((read != 0) && (set[read] != current_set)) {
- /* Latch different code set */
- switch (set[read]) {
- case 'A':
- values[bar_characters++] = 101;
- current_set = 'A';
- break;
- case 'B':
- values[bar_characters++] = 100;
- current_set = 'B';
- break;
- case 'C':
- values[bar_characters++] = 99;
- current_set = 'C';
- break;
- }
- }
-
if (read != 0) {
+ if (set[read] != current_set) {
+ /* Latch different code set */
+ switch (set[read]) {
+ case 'A':
+ values[bar_characters++] = 101;
+ current_set = 'A';
+ break;
+ case 'B':
+ values[bar_characters++] = 100;
+ current_set = 'B';
+ break;
+ case 'C':
+ values[bar_characters++] = 99;
+ current_set = 'C';
+ break;
+ }
+ }
+
if ((fset[read] == 'F') && (f_state == 0)) {
/* Latch beginning of extended mode */
switch (current_set) {
@@ -690,18 +711,24 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
values[bar_characters++] = 98;
}
- switch (set[read]) { /* Encode data characters */
- case 'a':
- case 'A': c128_set_a(src[read], values, &bar_characters);
- read++;
- break;
- case 'b':
- case 'B': (void) c128_set_b(src[read], values, &bar_characters);
- read++;
- break;
- case 'C': c128_set_c(src[read], src[read + 1], values, &bar_characters);
- read += 2;
- break;
+ if (!fncs[read]) {
+ switch (set[read]) { /* Encode data characters */
+ case 'a':
+ case 'A':
+ c128_set_a(src[read++], values, &bar_characters);
+ break;
+ case 'b':
+ case 'B':
+ (void) c128_set_b(src[read++], values, &bar_characters);
+ break;
+ case 'C':
+ c128_set_c(src[read], src[read + 1], values, &bar_characters);
+ read += 2;
+ break;
+ }
+ } else {
+ values[bar_characters++] = 102; /* FNC1 in all modes */
+ read++;
}
} while (read < length);
@@ -744,6 +771,16 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* ISO/IEC 15417:2007 leaves dimensions/height as application specification */
+ /* HRT */
+ if (have_fnc1) {
+ /* Remove any manual FNC1 dummies ('\x1D') */
+ for (i = 0, j = 0; i < length; i++) {
+ if (!fncs[i]) {
+ src[j++] = src[i];
+ }
+ }
+ length = j;
+ }
error_number = hrt_cpy_iso8859_1(symbol, src, length);
return error_number;
@@ -788,7 +825,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
indexliste = 0;
indexchaine = 0;
- mode = c128_parunmodd(reduced[indexchaine]);
+ mode = c128_parunmodd(reduced[indexchaine], 1 /*check_fnc1*/);
do {
list[1][indexliste] = mode;
@@ -798,10 +835,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
if (indexchaine == reduced_length) {
break;
}
- mode = c128_parunmodd(reduced[indexchaine]);
- if (reduced[indexchaine] == '\x1D') {
- mode = C128_ABORC;
- }
+ mode = c128_parunmodd(reduced[indexchaine], 1 /*check_fnc1*/);
}
indexliste++;
} while (indexchaine < reduced_length);
@@ -853,7 +887,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
break;
}
- values[bar_characters++] = 102;
+ values[bar_characters++] = 102; /* FNC1 */
/* Encode the data */
read = 0;
@@ -882,13 +916,11 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
switch (set[read]) { /* Encode data characters */
case 'A':
case 'a':
- c128_set_a(reduced[read], values, &bar_characters); /* Not reached */
- read++;
+ c128_set_a(reduced[read++], values, &bar_characters); /* Not reached */
break;
case 'B':
case 'b':
- (void) c128_set_b(reduced[read], values, &bar_characters);
- read++;
+ (void) c128_set_b(reduced[read++], values, &bar_characters);
break;
case 'C':
c128_set_c(reduced[read], reduced[read + 1], values, &bar_characters);
@@ -896,7 +928,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
break;
}
} else {
- values[bar_characters++] = 102;
+ values[bar_characters++] = 102; /* FNC1 in all modes */
read++;
}
} while (read < reduced_length);
@@ -1194,8 +1226,7 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length)
case 21:
case 24:
case 27:
- symbol->text[p] = ' ';
- p++;
+ symbol->text[p++] = ' ';
break;
}
}
diff --git a/backend/code128.h b/backend/code128.h
index 4b1c573c..3102eb60 100644
--- a/backend/code128.h
+++ b/backend/code128.h
@@ -1,6 +1,6 @@
/*
libzint - the open source barcode library
- Copyright (C) 2020-2023 Robin Stuart
+ Copyright (C) 2020-2024 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -49,7 +49,7 @@ extern "C" {
INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length);
-INTERNAL int c128_parunmodd(const unsigned char llyth);
+INTERNAL int c128_parunmodd(const unsigned char llyth, const int check_fnc1);
INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste, const char *manual_set);
INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars);
INTERNAL int c128_set_b(const unsigned char source, int values[], int *bar_chars);
diff --git a/backend/code16k.c b/backend/code16k.c
index 4f122b8e..bd757955 100644
--- a/backend/code16k.c
+++ b/backend/code16k.c
@@ -90,7 +90,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
indexliste = 0;
indexchaine = 0;
- mode = c128_parunmodd(source[indexchaine]);
+ mode = c128_parunmodd(source[indexchaine], gs1 /*check_fnc1*/);
do {
list[1][indexliste] = mode;
@@ -100,10 +100,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
if (indexchaine == length) {
break;
}
- mode = c128_parunmodd(source[indexchaine]);
- if (gs1 && source[indexchaine] == '\x1D') {
- mode = C128_ABORC;
- } /* FNC1 */
+ mode = c128_parunmodd(source[indexchaine], gs1 /*check_fnc1*/);
}
indexliste++;
} while (indexchaine < length);
diff --git a/backend/raster.c b/backend/raster.c
index 4eebe26c..5e3a62d8 100644
--- a/backend/raster.c
+++ b/backend/raster.c
@@ -68,7 +68,7 @@ static void *raster_malloc(size_t size, size_t size2) {
/* Check for large image `malloc`s, which produce very large files most systems can't handle anyway */
/* Also `malloc()` on Linux will (usually) succeed regardless of request, and then get untrappably killed on
access by OOM killer if too much, so this is a crude mitigation */
- if (size + size2 > 0x40000000) { /* 1GB */
+ if (size + size2 < size /*Overflow check*/ || size + size2 > 0x40000000 /*1GB*/) {
return NULL;
}
return malloc(size);
@@ -112,7 +112,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
symbol->alphamap = NULL;
}
- symbol->bitmap = (unsigned char *) raster_malloc(bm_bitmap_size, 0);
+ symbol->bitmap = (unsigned char *) raster_malloc(bm_bitmap_size, 0 /*size2*/);
if (symbol->bitmap == NULL) {
strcpy(symbol->errtxt, "661: Insufficient memory for bitmap buffer");
return ZINT_ERROR_MEMORY;
@@ -783,7 +783,7 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, const int rotate_ang
assert(image_width && image_height);
image_size = (size_t) image_width * image_height;
- if (!(pixelbuf = (unsigned char *) raster_malloc(image_size, 0 /*size*/))) {
+ if (!(pixelbuf = (unsigned char *) raster_malloc(image_size, 0 /*size2*/))) {
strcpy(symbol->errtxt, "655: Insufficient memory for pixel buffer");
return ZINT_ERROR_MEMORY;
}
diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c
index a31d62c0..da78c1d5 100644
--- a/backend/tests/test_code128.c
+++ b/backend/tests/test_code128.c
@@ -370,6 +370,19 @@ static void test_input(const testCtx *const p_ctx) {
/* 78*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "A\\^", -1, 0, 68, 1, "(6) 104 33 60 62 31 106", "StartC 12 34 CodeB A B C CodeC 12 CodeA LF" },
/* 79*/ { UNICODE_MODE, "A\0121234A12\012", -1, 0, 145, 1, "(13) 103 33 74 99 12 34 101 33 17 18 74 99 106", "StartA A CodeC 12 34 CodeA A 1 2 ; Okapi c128/improved-lookahead-mode-a.png" },
/* 80*/ { UNICODE_MODE, "21*\015\012M0", -1, 0, 112, 1, "(10) 103 18 17 10 77 74 45 16 9 106", "StartA 2 1 * M 0; Okapi c128/improved-lookahead-rule-1c.png" },
+ /* 81*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "\\^1SN123456789012", -1, 0, 145, 1, "(13) 104 102 51 46 99 12 34 56 78 90 12 65 106", "StartB FNC1 S N CodeC 12 34 56 78 90 12" },
+ /* 82*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "\\^B\\^1SN123456789012", -1, 0, 200, 0, "(18) 104 102 51 46 17 18 19 20 21 22 23 24 25 16 17 18 56 106", "StartB FNC1 S N 1 2 3 4 5 6 7 8 9 0 1 2; BWIPP no manual mode" },
+ /* 83*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "A\\^1BC\\^1DEF\\^1", -1, 0, 134, 1, "(12) 104 33 102 34 35 102 36 37 38 102 9 106", "StartB A FNC1 B C FNC1 D E F FNC1" },
+ /* 84*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "\\^C12\\^1", -1, 0, 57, 0, "(5) 105 12 102 12 106", "StartC 12 FNC1; BWIPP no manual mode" },
+ /* 85*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "12\\^13", -1, 0, 79, 1, "(7) 105 12 102 100 19 79 106", "StartC 12 FNC1 CodeB 3" },
+ /* 86*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "12\\^13\\^1", -1, 0, 90, 1, "(8) 105 12 102 100 19 102 74 106", "StartC 12 FNC1 CodeB 3 FNC1" },
+ /* 87*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "1\\^123", -1, 0, 79, 0, "(7) 104 17 99 102 23 99 106", "StartB 1 CodeC FNC1 23; BWIPP different encodation (same codeword count)" },
+ /* 88*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "12\\^134", -1, 0, 68, 1, "(6) 105 12 102 34 11 106", "StartC 12 FNC1 34" },
+ /* 89*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "12\\^134\\^1", -1, 0, 79, 1, "(7) 105 12 102 34 102 7 106", "StartC 12 FNC1 34 FNC1" },
+ /* 90*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "123\\^145\\^1", -1, 0, 112, 0, "(10) 105 12 100 19 99 102 45 102 101 106", "StartC 12 CodeB 3 CodeC FNC1 45 FNC1; BWIPP different encodation (BWIPP 1 shorter)" },
+ /* 91*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "12\\^1345\\^1", -1, 0, 112, 0, "(10) 105 12 102 100 19 99 45 102 13 106", "StartC 12 FNC1 CodeB 3 CodeC 45 FNC1; BWIPP different encodation (BWIPP 1 shorter)" },
+ /* 92*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "1234\\^156\\^1", -1, 0, 90, 1, "(8) 105 12 34 102 56 102 92 106", "StartC 12 34 FNC1 56 FNC1" },
+ /* 93*/ { UNICODE_MODE | EXTRA_ESCAPE_MODE, "1234\\^156789\\^101\\^11\\^1", -1, 0, 189, 0, "(17) 105 12 34 102 100 21 99 67 89 102 1 102 100 17 102 48 106", "StartC 12 34 FNC1 56 78 CodeB 9 CodeC FNC1 01 FNC1 CodeB 1 FNC1; BWIPP different encodation (BWIPP 1 shorter)" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
@@ -449,45 +462,51 @@ static void test_gs1_128_input(const testCtx *const p_ctx) {
char *data;
int ret;
int expected_width;
+ int bwipp_cmp;
char *expected;
char *comment;
};
struct item data[] = {
- /* 0*/ { GS1_MODE, "[90]1[90]1", 0, 123, "(11) 105 102 90 100 17 102 25 99 1 56 106", "StartC FNC1 90 CodeB 1 FNC1 9" },
- /* 1*/ { GS1_MODE | GS1PARENS_MODE, "(90)1(90)1", 0, 123, "(11) 105 102 90 100 17 102 25 99 1 56 106", "StartC FNC1 90 CodeB 1 FNC1 9" },
- /* 2*/ { GS1_MODE, "[90]1[90]12", 0, 123, "(11) 105 102 90 100 17 99 102 90 12 13 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12" },
- /* 3*/ { GS1_MODE, "[90]1[90]123", 0, 134, "(12) 105 102 90 100 17 102 25 99 1 23 57 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23" },
- /* 4*/ { GS1_MODE, "[90]12[90]1", 0, 123, "(11) 105 102 90 12 102 100 25 99 1 19 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01" },
- /* 5*/ { GS1_MODE, "[90]12[90]12", 0, 101, "(9) 105 102 90 12 102 90 12 14 106", "StartC FNC1 90 12 FNC1 90 12" },
- /* 6*/ { GS1_MODE, "[90]12[90]123", 0, 134, "(12) 105 102 90 12 102 100 25 99 1 23 20 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23" },
- /* 7*/ { GS1_MODE, "[90]123[90]1", 0, 134, "(12) 105 102 90 12 100 19 102 25 99 1 34 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01" },
- /* 8*/ { GS1_MODE, "[90]123[90]1234", 0, 145, "(13) 105 102 90 12 100 19 99 102 90 12 34 98 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34" },
- /* 9*/ { GS1_MODE, "[90]1[90]1[90]1", 0, 178, "(16) 105 102 90 100 17 102 25 99 1 102 100 25 99 1 51 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 FNC1 CodeB 9 CodeC 01" },
- /* 10*/ { GS1_MODE, "[90]1[90]12[90]1", 0, 178, "(16) 105 102 90 100 17 99 102 90 12 102 100 25 99 1 8 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12 FNC1 CodeB 9 CodeC 01" },
- /* 11*/ { GS1_MODE, "[90]1[90]123[90]1", 0, 189, "(17) 105 102 90 100 17 102 25 99 1 23 102 100 25 99 1 70 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23 FNC1 CodeB 9 CodeC 01" },
- /* 12*/ { GS1_MODE, "[90]12[90]123[90]1", 0, 189, "(17) 105 102 90 12 102 100 25 99 1 23 102 100 25 99 1 33 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 CodeB 9 CodeC 01" },
- /* 13*/ { GS1_MODE, "[90]12[90]123[90]12", 0, 167, "(15) 105 102 90 12 102 100 25 99 1 23 102 90 12 11 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 90 12" },
- /* 14*/ { GS1_MODE, "[90]123[90]1[90]1", 0, 189, "(17) 105 102 90 12 100 19 102 25 99 1 102 100 25 99 1 47 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 FNC1 CodeB 9 CodeC 01" },
- /* 15*/ { GS1_MODE, "[90]123[90]12[90]1", 0, 189, "(17) 105 102 90 12 100 19 99 102 90 12 102 100 25 99 1 80 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 FNC1 CodeB 9 CodeC 01" },
- /* 16*/ { GS1_MODE, "[90]123[90]123[90]12", 0, 178, "(16) 105 102 90 12 100 19 102 25 99 1 23 102 90 12 47 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 23 FNC1 90 12" },
- /* 17*/ { GS1_MODE, "[90]123[90]1234[90]1", 0, 200, "(18) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 99 1 26 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01" },
- /* 18*/ { GS1_MODE, "[90]123[90]1234[90]123", 0, 211, "(19) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 99 1 23 85 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01 23" },
- /* 19*/ { GS1_MODE, "[90]12345[90]1234[90]1", 0, 211, "(19) 105 102 90 12 34 100 21 99 102 90 12 34 102 100 25 99 1 30 106", "StartC FNC1 90 12 34 CodeB 5 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01" },
- /* 20*/ { GS1_MODE, "[90]1A[90]1", 0, 134, "(12) 104 102 25 16 17 33 102 25 99 1 65 106", "StartB FNC1 9 0 1 A FNC1 9 CodeC 01" },
- /* 21*/ { GS1_MODE, "[90]12A[90]123", 0, 145, "(13) 105 102 90 12 100 33 102 25 99 1 23 25 106", "StartC FNC1 90 12 CodeB A FNC1 9 CodeC 01 23" },
- /* 22*/ { GS1_MODE, "[90]123[90]A234[90]123", 0, 244, "(22) 105 102 90 12 100 19 99 102 90 100 33 18 99 34 102 100 25 99 1 23 37 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 CodeB A 2 CodeC 34 FNC1 CodeB 9 CodeC 01 23" },
- /* 23*/ { GS1_MODE, "[90]12345A12345A", 0, 178, "(16) 105 102 90 12 34 100 21 33 17 99 23 45 100 33 59 106", "StartC FNC1 90 12 34 CodeB 5 A 1 CodeC 23 45 CodeB A [" },
- /* 24*/ { GS1_MODE, "[01]12345678901231[90]12345678901234567890123456789", 0, 321, "(29) 105 102 1 12 34 56 78 90 12 31 90 12 34 56 78 90 12 34 56 78 90 12 34 56 78 100 25 59", "Max length" },
- /* 25*/ { GS1_MODE, "[01]12345678901231[90]123456789012345678901234567890[91]1", ZINT_WARN_NONCOMPLIANT, 365, "Warning 843: GS1-128 input too long (48 character maximum)", "Over length" },
- /* 26*/ { GS1_MODE, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890[93]1234", ZINT_WARN_HRT_TRUNCATED, 1135, "Warning 844: Human Readable Text truncated", "Max input" },
- /* 27*/ { GS1_MODE, "[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[3100]567890[20]34[20]78", ZINT_WARN_HRT_TRUNCATED, 1135, "Warning 844: Human Readable Text truncated", "HRT truncation warning trumps non-compliant (3100) warning" },
- /* 28*/ { GS1_MODE, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890[93]12345", ZINT_ERROR_TOO_LONG, 0, "Error 344: Input too long (99 symbol character maximum)", "" },
+ /* 0*/ { GS1_MODE, "[90]1[90]1", 0, 123, 1, "(11) 105 102 90 100 17 102 25 16 17 15 106", "StartC FNC1 90 CodeB 1 FNC1 9 0 1" },
+ /* 1*/ { GS1_MODE | GS1PARENS_MODE, "(90)1(90)1", 0, 123, 1, "(11) 105 102 90 100 17 102 25 16 17 15 106", "StartC FNC1 90 CodeB 1 FNC1 9 0 1" },
+ /* 2*/ { GS1_MODE, "[90]1[90]12", 0, 123, 0, "(11) 105 102 90 100 17 99 102 90 12 13 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12; BWIPP different encodation (same codeword count)" },
+ /* 3*/ { GS1_MODE, "[90]1[90]123", 0, 134, 1, "(12) 105 102 90 100 17 102 25 99 1 23 57 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23" },
+ /* 4*/ { GS1_MODE, "[90]12[90]1", 0, 112, 1, "(10) 105 102 90 12 102 90 100 17 43 106", "StartC FNC1 90 12 FNC1 90 CodeB 1" },
+ /* 5*/ { GS1_MODE, "[90]12[90]12", 0, 101, 1, "(9) 105 102 90 12 102 90 12 14 106", "StartC FNC1 90 12 FNC1 90 12" },
+ /* 6*/ { GS1_MODE, "[90]12[90]123", 0, 123, 1, "(11) 105 102 90 12 102 90 12 100 19 42 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23" },
+ /* 7*/ { GS1_MODE, "[90]123[90]1", 0, 134, 1, "(12) 105 102 90 12 100 19 102 25 16 17 29 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 0 1" },
+ /* 8*/ { GS1_MODE, "[90]123[90]1234", 0, 145, 0, "(13) 105 102 90 12 100 19 99 102 90 12 34 98 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34; BWIPP different encodation (same codeword count)" },
+ /* 9*/ { GS1_MODE, "[90]1[90]1[90]1", 0, 178, 0, "(16) 105 102 90 100 17 102 25 99 1 102 100 25 16 17 87 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 FNC1 CodeB 9 0 1; BWIPP different encodation (BWIPP 1 shorter)" },
+ /* 10*/ { GS1_MODE, "[90]1[90]12[90]1", 0, 178, 0, "(16) 105 102 90 100 17 99 102 90 12 102 100 25 16 17 44 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12 FNC1 CodeB 9 0 1; BWIPP different encodation (same codeword count)" },
+ /* 11*/ { GS1_MODE, "[90]1[90]123[90]1", 0, 189, 0, "(17) 105 102 90 100 17 102 25 99 1 23 102 100 25 16 17 39 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23 FNC1 CodeB 9 0 1; BWIPP different encodation (BWIPP 1 shorter)" },
+ /* 12*/ { GS1_MODE, "[90]12[90]123[90]1", 0, 189, 0, "(17) 105 102 90 12 102 100 25 99 1 23 102 100 25 16 17 2 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 CodeB 9 0 1; BWIPP different encodation (BWIPP 2 shorter)" },
+ /* 13*/ { GS1_MODE, "[90]12[90]123[90]12", 0, 167, 0, "(15) 105 102 90 12 102 100 25 99 1 23 102 90 12 11 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 90 12; BWIPP different encodation (same codeword count)" },
+ /* 14*/ { GS1_MODE, "[90]123[90]1[90]1", 0, 189, 0, "(17) 105 102 90 12 100 19 102 25 99 1 102 100 25 16 17 16 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 FNC1 CodeB 9 0 1; BWIPP different encodation (BWIPP 1 shorter)" },
+ /* 15*/ { GS1_MODE, "[90]123[90]12[90]1", 0, 189, 0, "(17) 105 102 90 12 100 19 99 102 90 12 102 100 25 16 17 49 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 FNC1 CodeB 9 CodeC 01; BWIPP different encodation (same codeword count)" },
+ /* 16*/ { GS1_MODE, "[90]123[90]123[90]12", 0, 178, 1, "(16) 105 102 90 12 100 19 102 25 99 1 23 102 90 12 47 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 23 FNC1 90 12" },
+ /* 17*/ { GS1_MODE, "[90]123[90]1234[90]1", 0, 200, 0, "(18) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 16 17 31 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01; BWIPP different encodation (BWIPP 1 longer)" },
+ /* 18*/ { GS1_MODE, "[90]123[90]1234[90]123", 0, 211, 0, "(19) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 99 1 23 85 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01 23; BWIPP different encodation (BWIPP 1 longer)" },
+ /* 19*/ { GS1_MODE, "[90]12345[90]1234[90]1", 0, 211, 0, "(19) 105 102 90 12 34 100 21 99 102 90 12 34 102 100 25 16 17 71 106", "StartC FNC1 90 12 34 CodeB 5 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01; BWIPP different encodation (BWIPP 1 longer)" },
+ /* 20*/ { GS1_MODE, "[90]1A[90]1", 0, 134, 0, "(12) 104 102 25 16 17 33 102 25 16 17 60 106", "StartB FNC1 9 0 1 A FNC1 9 CodeC 01; BWIPP different encodation (same codeword count)" },
+ /* 21*/ { GS1_MODE, "[90]12A[90]123", 0, 145, 1, "(13) 105 102 90 12 100 33 102 25 99 1 23 25 106", "StartC FNC1 90 12 CodeB A FNC1 9 CodeC 01 23" },
+ /* 22*/ { GS1_MODE, "[90]123[90]A234[90]123", 0, 244, 0, "(22) 105 102 90 12 100 19 99 102 90 100 33 18 99 34 102 100 25 99 1 23 37 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 CodeB A 2 CodeC 34 FNC1 CodeB 9 CodeC 01 23; BWIPP different encodation (BWIPP 2 shorter)" },
+ /* 23*/ { GS1_MODE, "[90]12345A12345A", 0, 178, 1, "(16) 105 102 90 12 34 100 21 33 17 99 23 45 100 33 59 106", "StartC FNC1 90 12 34 CodeB 5 A 1 CodeC 23 45 CodeB A" },
+ /* 24*/ { GS1_MODE, "[01]12345678901231[90]12345678901234567890123456789", 0, 321, 1, "(29) 105 102 1 12 34 56 78 90 12 31 90 12 34 56 78 90 12 34 56 78 90 12 34 56 78 100 25 59", "Max length" },
+ /* 25*/ { GS1_MODE, "[01]12345678901231[90]123456789012345678901234567890[91]1", ZINT_WARN_NONCOMPLIANT, 354, 1, "Warning 843: GS1-128 input too long (48 character maximum)", "Over length" },
+ /* 26*/ { GS1_MODE, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890[93]1234", ZINT_WARN_HRT_TRUNCATED, 1135, 1, "Warning 844: Human Readable Text truncated", "Max input" },
+ /* 27*/ { GS1_MODE, "[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[00]345678901234567890[3100]567890[20]34[20]78", ZINT_WARN_HRT_TRUNCATED, 1135, 1, "Warning 844: Human Readable Text truncated", "HRT truncation warning trumps non-compliant (3100) warning" },
+ /* 28*/ { GS1_MODE, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345678901234567890[93]12345", ZINT_ERROR_TOO_LONG, 0, 1, "Error 344: Input too long (99 symbol character maximum)", "" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol = NULL;
char escaped[1024];
+ char cmp_buf[8192];
+ char cmp_msg[1024];
+
+ int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
+ int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); /* Only do ZXing-C++ test if asked, too slow otherwise */
testStartSymbol("test_gs1_128_input", &symbol);
@@ -505,13 +524,14 @@ static void test_gs1_128_input(const testCtx *const p_ctx) {
length = testUtilSetSymbol(symbol, BARCODE_GS1_128, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
- assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (p_ctx->generate) {
- printf(" /*%3d*/ { %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n",
+ printf(" /*%3d*/ { %s, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n",
i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
- testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment);
+ testUtilErrorName(data[i].ret), symbol->width, data[i].bwipp_cmp, symbol->errtxt, data[i].comment);
} else {
+ assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
+ assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0 (width %d)\n", i, symbol->errtxt, data[i].expected, symbol->width);
if (ret < ZINT_ERROR) {
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
if (ret == ZINT_WARN_HRT_TRUNCATED) {
@@ -521,8 +541,33 @@ static void test_gs1_128_input(const testCtx *const p_ctx) {
assert_equal((int) ustrlen(symbol->text), (int) strlen(data[i].data), "i:%d len symbol->text(%s) %d != %d (%s, %s) (%s)\n",
i, symbol->text, (int) ustrlen(symbol->text), (int) strlen(data[i].data), testUtilErrorName(ret), data[i].data, symbol->errtxt);
}
+
+ if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) {
+ if (!data[i].bwipp_cmp) {
+ if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment);
+ } else {
+ char modules_dump[4096];
+ assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i);
+ ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf), NULL);
+ assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
+
+ ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, modules_dump);
+ assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
+ i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_buf, modules_dump);
+ }
+ }
+ if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data[i].data, length, debug)) {
+ int cmp_len, ret_len;
+ char modules_dump[4096];
+ assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i);
+ ret = testUtilZXingCPP(i, symbol, data[i].data, length, modules_dump, cmp_buf, sizeof(cmp_buf), &cmp_len);
+ assert_zero(ret, "i:%d %s testUtilZXingCPP ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
+
+ ret = testUtilZXingCPPCmp(symbol, cmp_msg, cmp_buf, cmp_len, data[i].data, length, NULL /*primary*/, escaped, &ret_len);
+ assert_zero(ret, "i:%d %s testUtilZXingCPPCmp %d != 0 %s\n actual: %.*s\nexpected: %.*s\n",
+ i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped);
+ }
}
- assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected);
}
ZBarcode_Delete(symbol);
@@ -556,6 +601,11 @@ static void test_hibc_input(const testCtx *const p_ctx) {
struct zint_symbol *symbol = NULL;
char escaped[1024];
+ char cmp_buf[8192];
+ char cmp_msg[1024];
+
+ int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */
+ int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); /* Only do ZXing-C++ test if asked, too slow otherwise */
testStartSymbol("test_hibc_input", &symbol);
@@ -578,10 +628,32 @@ static void test_hibc_input(const testCtx *const p_ctx) {
i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment);
} else {
+ assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0 (width %d)\n", i, symbol->errtxt, data[i].expected, symbol->width);
if (ret < ZINT_ERROR) {
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
+
+ if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) {
+ char modules_dump[4096];
+ assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i);
+ ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf), NULL);
+ assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
+
+ ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, modules_dump);
+ assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
+ i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_buf, modules_dump);
+ }
+ if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data[i].data, length, debug)) {
+ int cmp_len, ret_len;
+ char modules_dump[4096];
+ assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i);
+ ret = testUtilZXingCPP(i, symbol, data[i].data, length, modules_dump, cmp_buf, sizeof(cmp_buf), &cmp_len);
+ assert_zero(ret, "i:%d %s testUtilZXingCPP ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
+
+ ret = testUtilZXingCPPCmp(symbol, cmp_msg, cmp_buf, cmp_len, data[i].data, length, NULL /*primary*/, escaped, &ret_len);
+ assert_zero(ret, "i:%d %s testUtilZXingCPPCmp %d != 0 %s\n actual: %.*s\nexpected: %.*s\n",
+ i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped);
+ }
}
- assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected);
}
ZBarcode_Delete(symbol);
diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c
index 0ca34ef2..a7bf55e1 100644
--- a/backend/tests/testcommon.c
+++ b/backend/tests/testcommon.c
@@ -2505,8 +2505,17 @@ static char *testUtilBwippEscape(char *bwipp_data, int bwipp_data_size, const ch
sprintf(b, "^%03d", val);
b += 4;
} else {
- if (d + 1 < de && *(d + 1) >= 'A' && *(d + 1) <= 'C') {
+ if (d + 1 < de && ((*(d + 1) >= 'A' && *(d + 1) <= 'C') || *(d + 1) == '1')) {
d++;
+ if (*d == '1') {
+ if (b + 5 >= be) {
+ fprintf(stderr, "testUtilBwippEscape: FNC1 bwipp_data buffer full (%d)\n", bwipp_data_size);
+ return NULL;
+ }
+ strcpy(b, "^FNC1");
+ b += 5;
+ *parsefnc = 1;
+ }
} else {
if (b + 8 >= be) {
fprintf(stderr, "testUtilBwippEscape: loop bwipp_data buffer full (%d)\n", bwipp_data_size);
@@ -3960,9 +3969,18 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in
int j = 0;
for (i = 0; i < expected_len; i++) {
if (escaped[i] == '\\' && i + 2 < expected_len && escaped[i + 1] == '^'
- && ((escaped[i + 2] >= 'A' && escaped[i + 2] <= 'C') || escaped[i + 2] == '^')) {
+ && ((escaped[i + 2] >= 'A' && escaped[i + 2] <= 'C') || escaped[i + 2] == '1'
+ || escaped[i + 2] == '^')) {
if (escaped[i + 2] != '^') {
i += 2;
+ if (escaped[i] == '1') {
+ /* FNC1 in 1st position treated as GS1 and in 2nd position AIM, neither transmitted */
+ if (j > 2 || (j == 1 && !(z_isupper(escaped[0]) || z_islower(escaped[0])))
+ /* TODO: following exception only valid if in Code Set C */
+ || (j == 2 && !(z_isdigit(escaped[0]) && z_isdigit(escaped[1])))) {
+ escaped[j++] = 29; /* GS */
+ }
+ }
} else {
escaped[j++] = escaped[i++];
escaped[j++] = escaped[i++];
diff --git a/backend/tests/tools/bwipp_dump.ps.tar.xz b/backend/tests/tools/bwipp_dump.ps.tar.xz
index 7d163eb6..37dde529 100644
Binary files a/backend/tests/tools/bwipp_dump.ps.tar.xz and b/backend/tests/tools/bwipp_dump.ps.tar.xz differ
diff --git a/backend/tests/tools/run_bwipp_tests.sh b/backend/tests/tools/run_bwipp_tests.sh
index 421fef6e..0bae754f 100755
--- a/backend/tests/tools/run_bwipp_tests.sh
+++ b/backend/tests/tools/run_bwipp_tests.sh
@@ -1,5 +1,6 @@
#!/bin/bash
-# Copyright (C) 2020 - 2021 Robin Stuart
+# Copyright (C) 2021-2024 Robin Stuart
+# SPDX-License-Identifier: BSD-3-Clause
# vim: set ts=4 sw=4 et :
set -e
@@ -28,6 +29,8 @@ run_bwipp_test "test_code1" "encode"
run_bwipp_test "test_code1" "encode_segs"
run_bwipp_test "test_code1" "fuzz"
run_bwipp_test "test_code128" "input"
+run_bwipp_test "test_code128" "gs1_128_input"
+run_bwipp_test "test_code128" "hibc_input"
run_bwipp_test "test_code128" "encode"
run_bwipp_test "test_code16k" "input"
run_bwipp_test "test_code16k" "encode"
diff --git a/backend/tests/tools/run_zxingcpp_tests.sh b/backend/tests/tools/run_zxingcpp_tests.sh
index be1a2049..73bb1e5f 100755
--- a/backend/tests/tools/run_zxingcpp_tests.sh
+++ b/backend/tests/tools/run_zxingcpp_tests.sh
@@ -1,5 +1,6 @@
#!/bin/bash
-# Copyright (C) 2021-2022 Robin Stuart
+# Copyright (C) 2021-2024 Robin Stuart
+# SPDX-License-Identifier: BSD-3-Clause
# vim: set ts=4 sw=4 et :
set -e
@@ -23,6 +24,8 @@ run_zxingcpp_test "test_codablock" "encode"
run_zxingcpp_test "test_codablock" "fuzz"
run_zxingcpp_test "test_code" "encode"
run_zxingcpp_test "test_code128" "input"
+run_zxingcpp_test "test_code128" "gs1_128_input"
+run_zxingcpp_test "test_code128" "hibc_input"
run_zxingcpp_test "test_code128" "encode"
run_zxingcpp_test "test_code16k" "input"
run_zxingcpp_test "test_code16k" "encode"
diff --git a/backend/vector.c b/backend/vector.c
index b95f4d54..2ac51cf2 100644
--- a/backend/vector.c
+++ b/backend/vector.c
@@ -1,7 +1,7 @@
/* vector.c - Creates vector image objects */
/*
libzint - the open source barcode library
- Copyright (C) 2018-2023 Robin Stuart
+ Copyright (C) 2018-2024 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,8 +42,7 @@ static int vector_add_rect(struct zint_symbol *symbol, const float x, const floa
const float height, struct zint_vector_rect **last_rect) {
struct zint_vector_rect *rect;
- rect = (struct zint_vector_rect *) malloc(sizeof(struct zint_vector_rect));
- if (!rect) {
+ if (!(rect = (struct zint_vector_rect *) malloc(sizeof(struct zint_vector_rect)))) {
strcpy(symbol->errtxt, "691: Insufficient memory for vector rectangle");
return 0;
}
@@ -69,8 +68,7 @@ static int vector_add_hexagon(struct zint_symbol *symbol, const float x, const f
const float diameter, struct zint_vector_hexagon **last_hexagon) {
struct zint_vector_hexagon *hexagon;
- hexagon = (struct zint_vector_hexagon *) malloc(sizeof(struct zint_vector_hexagon));
- if (!hexagon) {
+ if (!(hexagon = (struct zint_vector_hexagon *) malloc(sizeof(struct zint_vector_hexagon)))) {
strcpy(symbol->errtxt, "692: Insufficient memory for vector hexagon");
return 0;
}
@@ -94,8 +92,7 @@ static int vector_add_circle(struct zint_symbol *symbol, const float x, const fl
const float width, const int colour, struct zint_vector_circle **last_circle) {
struct zint_vector_circle *circle;
- circle = (struct zint_vector_circle *) malloc(sizeof(struct zint_vector_circle));
- if (!circle) {
+ if (!(circle = (struct zint_vector_circle *) malloc(sizeof(struct zint_vector_circle)))) {
strcpy(symbol->errtxt, "693: Insufficient memory for vector circle");
return 0;
}
@@ -121,8 +118,7 @@ static int vector_add_string(struct zint_symbol *symbol, const unsigned char *te
struct zint_vector_string **last_string) {
struct zint_vector_string *string;
- string = (struct zint_vector_string *) malloc(sizeof(struct zint_vector_string));
- if (!string) {
+ if (!(string = (struct zint_vector_string *) malloc(sizeof(struct zint_vector_string)))) {
strcpy(symbol->errtxt, "694: Insufficient memory for vector string");
return 0;
}
@@ -134,8 +130,7 @@ static int vector_add_string(struct zint_symbol *symbol, const unsigned char *te
string->length = length == -1 ? (int) ustrlen(text) : length;
string->rotation = 0;
string->halign = halign;
- string->text = (unsigned char *) malloc(string->length + 1);
- if (!string->text) {
+ if (!(string->text = (unsigned char *) malloc(string->length + 1))) {
free(string);
strcpy(symbol->errtxt, "695: Insufficient memory for vector string text");
return 0;
@@ -449,8 +444,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
}
/* Allocate memory */
- vector = symbol->vector = (struct zint_vector *) malloc(sizeof(struct zint_vector));
- if (!vector) {
+ if (!(vector = symbol->vector = (struct zint_vector *) malloc(sizeof(struct zint_vector)))) {
strcpy(symbol->errtxt, "696: Insufficient memory for vector header");
return ZINT_ERROR_MEMORY;
}
diff --git a/docs/README b/docs/README
index 9bf3b7be..37c3afac 100644
--- a/docs/README
+++ b/docs/README
@@ -1,11 +1,11 @@
-% docs/README 2024-06-27
+% docs/README 2024-09-03
For generation of "docs/manual.pdf" and "docs/manual.txt" from "manual.pmd" using a recent version of pandoc
On Ubuntu/Debian (tested on Ubuntu 22.04)
- wget https://github.com/jgm/pandoc/releases/download/3.2.1/pandoc-3.2.1-1-amd64.deb
- sudo dpkg -i pandoc-3.2.1-1-amd64.deb
+ wget https://github.com/jgm/pandoc/releases/download/3.3/pandoc-3.3-1-amd64.deb
+ sudo dpkg -i pandoc-3.3-1-amd64.deb
sudo apt install python3-pip
pip install pandoc-tablenos --user
export PATH=~/.local/bin:"$PATH"
@@ -20,9 +20,9 @@ On Ubuntu/Debian (tested on Ubuntu 22.04)
On Fedora (tested on Fedora Linux 38 (Workstation Edition))
- wget https://github.com/jgm/pandoc/releases/download/3.2.1/pandoc-3.2.1-linux-amd64.tar.gz
- tar xf pandoc-3.2.1-linux-amd64.tar.gz
- sudo mv -i pandoc-3.2.1/bin/pandoc /usr/local/bin
+ wget https://github.com/jgm/pandoc/releases/download/3.3/pandoc-3.3-linux-amd64.tar.gz
+ tar xf pandoc-3.3-linux-amd64.tar.gz
+ sudo mv -i pandoc-3.3/bin/pandoc /usr/local/bin
sudo dnf install python3-pip
pip install pandoc-tablenos --user
export PATH=~/.local/bin:"$PATH"
diff --git a/docs/manual.html b/docs/manual.html
index b1c25918..68ab1f43 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -332,7 +332,7 @@
Zint Barcode Generator and Zint Barcode Studio User
Manual
Version 2.13.0.9
-June 2024
+September 2024
Input data can be read directly from file using the -i
or --input
switch as shown below. The input file is assumed
to be UTF-8 formatted unless an alternative mode is selected. This
@@ -4831,6 +4832,11 @@ special code sequence, it can be escaped by doubling the caret
zint -b CODE128 -d "\^AABC\^^BDEF" --extraesc
will encode the data "ABC\^BDEF"
in Code Set A.
+There is also the extra escape \^1
, which will encode a
+special Function Code 1 character (FNC1) anywhere you chose in the data,
+for instance
+zint -b CODE128 -d "A\^1BC\^1DEF" --extraesc
Code 128 is the default barcode symbology used by Zint. In addition
Zint supports the encoding of ISO/IEC 8859-1 (non-English) characters in
Code 128 symbols. The ISO/IEC 8859-1 character set is shown in Annex BARCODE_CODE128AB variant (symbology 60) suppresses
Code Set C in favour of Code Sets A and B.
-Note that the special escapes to manually switch Code Sets mentioned
-above are not available for this variant (nor for any other).
+Note that the special extra escapes mentioned above are not available
+for this variant (nor for any other).
6.1.10.3 GS1-128
-zint -b 16 -d "[01]98898765432106[3202]012345[15]991231"
-or using the --gs1parens
option:
zint -b 16 --gs1parens -d "(01)98898765432106(3202)012345(15)991231"
+class="sourceCode bash">zint -b 16 -d "[01]98898765432106[3202]012345[15]991231"
+or using the --gs1parens
option:
+zint -b 16 --gs1parens -d "(01)98898765432106(3202)012345(15)991231"
6.1.10.4 EAN-14
6.1.10.3 GS1-128.
not calculated by Zint when this symbology is encoded. Fixed length data
should be entered at the appropriate length for correct encoding. The
following is an example of a valid GS1 DataBar Expanded input:
-zint -b 31 -d "[01]98898765432106[3202]012345[15]991231"
+zint -b 31 -d "[01]98898765432106[3202]012345[15]991231"
6.1.12 Korea Post Barcode
primarily in the vehicle industry, is to simply stack one-dimensional
codes on top of each other. This can be achieved at the command prompt
by giving more than one set of input data. For example
-
+
will draw two Code 128 symbols, one on top of the other. The same
result can be achieved using the API by executing the
ZBarcode_Encode()
function more than once on a symbol. For
example:
- my_symbol-> symbology = BARCODE_CODE128;
-
- error = ZBarcode_Encode( my_symbol, "This" , 0 );
-
- error = ZBarcode_Encode( my_symbol, "That" , 0 );
-
- error = ZBarcode_Print( my_symbol);
+ my_symbol-> symbology = BARCODE_CODE128;
+
+ error = ZBarcode_Encode( my_symbol, "This" , 0 );
+
+ error = ZBarcode_Encode( my_symbol, "That" , 0 );
+
+ error = ZBarcode_Print( my_symbol);
@@ -5169,8 +5175,8 @@ specifying --bind
(API
separator bars in integral multiples of the X-dimension (minimum and
default 1, maximum 4) can be set by --separator
(API
option_3
):
-zint --bind --notext --separator = 2 -d "This" -d "That"
+zint --bind --notext --separator = 2 -d "This" -d "That"
@@ -5445,21 +5451,21 @@ should be entered into a primary string with the data for the 2D
component being entered in the normal way. To do this at the command
prompt use the --primary
switch (API primary
).
For example:
-zint -b EANX_CC --mode = 1 --primary = 331234567890 -d "[99]1234-abcd"
+zint -b EANX_CC --mode = 1 --primary = 331234567890 -d "[99]1234-abcd"
This creates an EAN-13 linear component with the data
"331234567890"
and a 2D CC-A (see below ) component with the data
"(99)1234-abcd"
. The same results can be achieved using the
API as shown below:
- my_symbol-> symbology = BARCODE_EANX_CC;
-
- my_symbol-> option_1 = 1 ;
-
- strcpy( my_symbol-> primary, "331234567890" );
-
- ZBarcode_Encode_and_Print( my_symbol, "[99]1234-abcd" , 0 , 0 );
+ my_symbol-> symbology = BARCODE_EANX_CC;
+
+ my_symbol-> option_1 = 1 ;
+
+ strcpy( my_symbol-> primary, "331234567890" );
+
+ ZBarcode_Encode_and_Print( my_symbol, "[99]1234-abcd" , 0 , 0 );
EAN-2 and EAN-5 add-on data can be used with EAN and UPC symbols
using the + symbol as described in sections 6.1.3 UPC (Universal
@@ -5819,13 +5825,13 @@ size to full height can be given in thousandths (permille) using the
--vers
option (API option_2
). The default
value is 250 (25%).
For example the following
-zint -b DAFT -d AAFDTTDAFADTFTTFFFDATFTADTTFFTDAFAFDTF --height = 8.494 --vers = 256
+zint -b DAFT -d AAFDTTDAFADTFTTFFFDATFTADTTFFTDAFAFDTF --height = 8.494 --vers = 256
produces the same barcode (see 6.5.3 Royal Mail 4-State
Customer Code (RM4SCC) ) as
-zint -b RM4SCC --compliantheight -d "W1J0TR01"
+zint -b RM4SCC --compliantheight -d "W1J0TR01"
6.6 Matrix Symbols
6.6.1 Data Matrix (ISO 16022)
@@ -6465,8 +6471,8 @@ be manually specified by using the --mask
switch with
values 0-7, or in the API by setting
option_3 = (N + 1) << 8
where N is 0-7. To use with
ZINT_FULL_MULTIBYTE
set
- option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
+ option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
The --fast
option (API
input_mode |= FAST_MODE
) may be used when leaving Zint to
automatically select a mask to reduce the number of masks to try to four
@@ -6602,8 +6608,8 @@ be manually specified by using the --mask
switch with
values 0-3, or in the API by setting
option_3 = (N + 1) << 8
where N is 0-3. To use with
ZINT_FULL_MULTIBYTE
set
- option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
+ option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
6.6.5 Rectangular
Micro QR Code (rMQR) (ISO 23941)
@@ -6870,8 +6876,8 @@ Latin-2 formatted use the --binary
switch (API
input_mode = DATA_MODE
).
The following example creates a symbol from data saved as a Latin-2
file:
-zint -o upnqr.png -b 143 --scale = 3 --binary -i upn.txt
+zint -o upnqr.png -b 143 --scale = 3 --binary -i upn.txt
A mask may be manually specified or the --fast
option
used as with QRCODE.
6.6.7 MaxiCode (ISO 16023)
@@ -6946,9 +6952,9 @@ your parcel courier.
The primary message can be set at the command prompt using the
--primary
switch (API primary
). The secondary
message uses the normal data entry method. For example:
-zint -o test.eps -b 57 --primary = "999999999840012" \
- -d "Secondary Message Here"
+zint -o test.eps -b 57 --primary = "999999999840012" \
+ -d "Secondary Message Here"
When using the API the primary message must be placed in the
primary
string. The secondary is entered in the same way as
described in 5.2 Encoding and
@@ -6961,9 +6967,9 @@ to be prefixed by the ISO/IEC 15434 Format "01"
vv
is a 2-digit version, by using the --scmvv
switch (API option_2 = vv + 1
). For example to use the
common version "96"
(ASC MH10/SC 8):
-zint -b 57 --primary = "152382802840001" --scmvv = 96 --esc -d \
- "1Z00004951\GUPSN\G06X610\G159\G1234567\G1/1\G\GY\G1 MAIN ST\GNY\GNY\R\E"
+zint -b 57 --primary = "152382802840001" --scmvv = 96 --esc -d \
+ "1Z00004951\GUPSN\G06X610\G159\G1234567\G1/1\G\GY\G1 MAIN ST\GNY\GNY\R\E"
will prefix "[)>\R01\G96"
to the secondary message.
(\R
, \G
and \E
are the escape
sequences for Record Separator, Group Separator and End of Transmission
@@ -6972,8 +6978,8 @@ Sequences.)
Modes 4 to 6 can be accessed using the --mode
switch
(API option_1
). Modes 4 to 6 do not have a primary message.
For example:
-zint -o test.eps -b 57 --mode = 4 -d "A MaxiCode Message in Mode 4"
+zint -o test.eps -b 57 --mode = 4 -d "A MaxiCode Message in Mode 4"
Mode 6 is reserved for the maintenance of scanner hardware and should
not be used to encode user data.
This symbology uses Latin-1 character encoding by default but also
@@ -7898,8 +7904,8 @@ be manually specified by using the --mask
switch with
values 0-3, or in the API by setting
option_3 = (N + 1) << 8
where N is 0-3. To use with
ZINT_FULL_MULTIBYTE
set
- option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
+ option_3 = ZINT_FULL_MULTIBYTE | ( N + 1 ) << 8
6.6.14 Ultracode
Zint does not currently implement data compression by default, but
this can be initiated through the API by setting
- symbol-> option_3 = ULTRA_COMPRESSION;
+ symbol-> option_3 = ULTRA_COMPRESSION;
With compression, up to 504 digits, 375 alphanumerics or 252 bytes
can be encoded.
Revision 2 of Ultracode (2023) may be specified using
@@ -8613,28 +8619,28 @@ properties that correspond to the zint_symbol
structure
method render()
which takes a Qt QPainter
to
paint with, and a QRectF
rectangular area specifying where
to paint into:
-/* Encode and display barcode in `paintRect` using `painter`.
- Note: legacy argument `mode` is not used */
-void render( QPainter & painter, const QRectF & paintRect,
- AspectRatioMode mode = IgnoreAspectRatio);
+/* Encode and display barcode in `paintRect` using `painter`.
+ Note: legacy argument `mode` is not used */
+void render( QPainter & painter, const QRectF & paintRect,
+ AspectRatioMode mode = IgnoreAspectRatio);
render()
will emit one of two Qt signals -
encoded
on successful encoding and drawing, or
errored
on failure. The client can connect and act
appropriately, for instance:
-connect ( qzint, SIGNAL ( encoded()), SLOT ( on_encoded()));
-connect ( qzint, SIGNAL ( errored()), SLOT ( on_errored()));
+connect ( qzint, SIGNAL ( encoded()), SLOT ( on_encoded()));
+connect ( qzint, SIGNAL ( errored()), SLOT ( on_errored()));
where qzint
is an instance of Zint::QZint
and on_encoded()
and on_error()
are Qt slot
methods provided by the caller. On error, the error value and message
can be retrieved by the methods getError()
and
lastError()
respectively.
The other main method is save_to_file()
:
-/* Encode and print barcode to file `filename`.
- Only sets `getError()` on error, not on warning */
-bool save_to_file( const QString & filename); // `ZBarcode_Print()`
+/* Encode and print barcode to file `filename`.
+ Only sets `getError()` on error, not on warning */
+bool save_to_file( const QString & filename); // `ZBarcode_Print()`
which takes a filename
to output to. It too will emit an
errored
signal on failure, returning false
(but nothing on success, which just returns true
). Note
@@ -8649,33 +8655,33 @@ symbology capabilities, and utility methods such as
Annex C. Tcl Backend Binding
A Tcl binding is available in the "backend_tcl
”
sub-directory. To make on Unix:
-cd backend_tcl
-autoconf
-./configure
-make
-sudo make install
+cd backend_tcl
+autoconf
+./configure
+make
+sudo make install
For Windows, a Visual Studio 6.0 project file is available at
"backend_tcl\zint_tcl.dsp"
. This can also be opened (and
converted) by more modern Visual Studio versions, though some fixing up
of the project configuration will likely be required.
Once built and installed, invoke the Tcl/Tk CLI
"wish"
:
-
+
and ignoring the Tk window click back to the command prompt
"%"
and type:
-require package zint
-zint help
+require package zint
+zint help
which will show the usage message, with options very similiar to the
Zint CLI. (One notable difference is that boolean options such as
-bold
take a 1
or 0
as an
argument.)
A demonstration Tcl/Tk program which is also useful in itself is
available at "backend_tcl/demo/demo.tcl"
. To run type:
-
+
which will display the following window.
--extraesc
-Process the special escape sequences \^A
,
-\^B
and \^C
that allow manual switching of
-Code Sets (Code 128 only). The sequence \^^
can be used to
-encode data that contains special escape sequences.
+For Code 128 only, process the special escape sequences
+\^A
, \^B
and \^C
that allow
+manual switching of Code Sets, and the special escape sequence
+\^1
that inserts an FNC1
character. The
+sequence \^^
can be used to encode data that contains
+special escape sequences.
--fast
@@ -9379,17 +9387,17 @@ Error counterpart of warning if --werror
given
EXAMPLES
Create “out.png” (or “out.gif” if zint built without PNG support) in
the current directory, as a Code 128 symbol.
-
-Create “qr.svg” in the current directory, as a QR Code symbol.
zint -b QRCode -d 'This Text' -o 'qr.svg'
+class="sourceCode bash">zint -d 'This Text'
+Create “qr.svg” in the current directory, as a QR Code symbol.
+zint -b QRCode -d 'This Text' -o 'qr.svg'
Use batch mode to read from an input file “ean13nos.txt” containing
13-digit GTINs, to create a series of EAN-13 barcodes, formatting the
output filenames to “ean001.gif”, “ean002.gif” etc. using the special
character “~”.
-zint -b EANX --batch -i 'ean13nos.txt' -o 'ean~~~.gif'
+zint -b EANX --batch -i 'ean13nos.txt' -o 'ean~~~.gif'
BUGS
Please send bug reports to
https://sourceforge.net/p/zint/tickets/.
diff --git a/docs/manual.pmd b/docs/manual.pmd
index ec4253c0..3dff515c 100644
--- a/docs/manual.pmd
+++ b/docs/manual.pmd
@@ -1,6 +1,6 @@
% Zint Barcode Generator and Zint Barcode Studio User Manual
% Version 2.13.0.9
-% June 2024
+% September 2024
# 1. Introduction
@@ -574,7 +574,8 @@ codeset from U+0000 to U+D7FF and U+E000 to U+FFFF (i.e. excluding surrogates).
Not to be confused with the Windows Bitmap file format BMP!
(Special escape sequences are available for Code 128 only to manually switch
-Code Sets - see [6.1.10.1 Standard Code 128 (ISO 15417)] for details.)
+Code Sets and/or insert special FNC1 characters - see [6.1.10.1 Standard Code
+128 (ISO 15417)] for details.)
Input data can be read directly from file using the `-i` or `--input` switch as
shown below. The input file is assumed to be UTF-8 formatted unless an
@@ -3131,6 +3132,13 @@ zint -b CODE128 -d "\^AABC\^^BDEF" --extraesc
will encode the data `"ABC\^BDEF"` in Code Set A.
+There is also the extra escape `\^1`, which will encode a special Function Code
+1 character (FNC1) anywhere you chose in the data, for instance
+
+```bash
+zint -b CODE128 -d "A\^1BC\^1DEF" --extraesc
+```
+
Code 128 is the default barcode symbology used by Zint. In addition Zint
supports the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128
symbols. The ISO/IEC 8859-1 character set is shown in Annex [A.2 Latin Alphabet
@@ -3147,8 +3155,8 @@ It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The `BARCODE_CODE128AB`[^14] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B.
-Note that the special escapes to manually switch Code Sets mentioned above are
-not available for this variant (nor for any other).
+Note that the special extra escapes mentioned above are not available for this
+variant (nor for any other).
[^14]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is
still recognised.
diff --git a/docs/manual.txt b/docs/manual.txt
index 1bbcec59..c2d2c940 100644
--- a/docs/manual.txt
+++ b/docs/manual.txt
@@ -1,6 +1,6 @@
Zint Barcode Generator and Zint Barcode Studio User Manual
Version 2.13.0.9
-June 2024
+September 2024
*******************************************************************************
* For reference the following is a text-only version of the Zint manual, *
@@ -720,7 +720,8 @@ sequences are shown in the table below.
Table : Escape Sequences
(Special escape sequences are available for Code 128 only to manually switch
-Code Sets - see 6.1.10.1 Standard Code 128 (ISO 15417) for details.)
+Code Sets and/or insert special FNC1 characters - see 6.1.10.1 Standard Code 128
+(ISO 15417) for details.)
Input data can be read directly from file using the -i or --input switch as
shown below. The input file is assumed to be UTF-8 formatted unless an
@@ -3029,6 +3030,11 @@ sequence, it can be escaped by doubling the caret (^). For instance
will encode the data "ABC\^BDEF" in Code Set A.
+There is also the extra escape \^1, which will encode a special Function Code 1
+character (FNC1) anywhere you chose in the data, for instance
+
+ zint -b CODE128 -d "A\^1BC\^1DEF" --extraesc
+
Code 128 is the default barcode symbology used by Zint. In addition Zint
supports the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128
symbols. The ISO/IEC 8859-1 character set is shown in Annex A.2 Latin Alphabet
@@ -3045,8 +3051,8 @@ It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The BARCODE_CODE128AB[14] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B.
-Note that the special escapes to manually switch Code Sets mentioned above are
-not available for this variant (nor for any other).
+Note that the special extra escapes mentioned above are not available for this
+variant (nor for any other).
6.1.10.3 GS1-128
@@ -4817,7 +4823,7 @@ configured barcode is displayed once the "Generate" button is pressed.
Annex D. Man Page ZINT(1)
-% ZINT(1) Version 2.13.0.9 % % June 2024
+% ZINT(1) Version 2.13.0.9 % % September 2024
NAME
@@ -5011,9 +5017,10 @@ OPTIONS
--extraesc
- Process the special escape sequences \^A, \^B and \^C that allow manual
- switching of Code Sets (Code 128 only). The sequence \^^ can be used to
- encode data that contains special escape sequences.
+ For Code 128 only, process the special escape sequences \^A, \^B and \^C
+ that allow manual switching of Code Sets, and the special escape sequence
+ \^1 that inserts an FNC1 character. The sequence \^^ can be used to encode
+ data that contains special escape sequences.
--fast
diff --git a/docs/zint.1 b/docs/zint.1
index fe50dadd..715819e7 100644
--- a/docs/zint.1
+++ b/docs/zint.1
@@ -1,6 +1,6 @@
-.\" Automatically generated by Pandoc 3.2
+.\" Automatically generated by Pandoc 3.3
.\"
-.TH "ZINT" "1" "June 2024" "Version 2.13.0.9" ""
+.TH "ZINT" "1" "September 2024" "Version 2.13.0.9"
.SH NAME
\f[CR]zint\f[R] \- encode data as a barcode image
.SH SYNOPSIS
@@ -195,9 +195,11 @@ The escape sequences are:
.RE
.TP
\f[CR]\-\-extraesc\f[R]
-Process the special escape sequences \f[CR]\[rs]\[ha]A\f[R],
-\f[CR]\[rs]\[ha]B\f[R] and \f[CR]\[rs]\[ha]C\f[R] that allow manual
-switching of Code Sets (Code 128 only).
+For Code 128 only, process the special escape sequences
+\f[CR]\[rs]\[ha]A\f[R], \f[CR]\[rs]\[ha]B\f[R] and
+\f[CR]\[rs]\[ha]C\f[R] that allow manual switching of Code Sets, and the
+special escape sequence \f[CR]\[rs]\[ha]1\f[R] that inserts an
+\f[CR]FNC1\f[R] character.
The sequence \f[CR]\[rs]\[ha]\[ha]\f[R] can be used to encode data that
contains special escape sequences.
.TP
diff --git a/docs/zint.1.pmd b/docs/zint.1.pmd
index fb2b46d0..58908cc9 100644
--- a/docs/zint.1.pmd
+++ b/docs/zint.1.pmd
@@ -1,6 +1,6 @@
% ZINT(1) Version 2.13.0.9
%
-% June 2024
+% September 2024
# NAME
@@ -174,8 +174,9 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S
`--extraesc`
-: Process the special escape sequences `\^A`, `\^B` and `\^C` that allow manual switching of Code Sets (Code 128
- only). The sequence `\^^` can be used to encode data that contains special escape sequences.
+: For Code 128 only, process the special escape sequences `\^A`, `\^B` and `\^C` that allow manual switching of Code
+ Sets, and the special escape sequence `\^1` that inserts an `FNC1` character. The sequence `\^^` can be used to
+ encode data that contains special escape sequences.
`--fast`
diff --git a/frontend_qt/grpC128.ui b/frontend_qt/grpC128.ui
index f5974ab2..9fec28d0 100644
--- a/frontend_qt/grpC128.ui
+++ b/frontend_qt/grpC128.ui
@@ -48,11 +48,12 @@
-
- &Manual Code Sets (Extra Escape Mode)
+ &Manual Code Sets and FNC1s (Extra Escape Mode)
- Process special escape sequences "\^A", "\^B" and
-"\^C" allowing manual Code Set selection
+ Process special escape sequences "\^A", "\^B" and "\^C"
+allowing manual Code Set selection and special escape
+sequence "\^1" allowing manual FNC1s