diff --git a/ChangeLog b/ChangeLog index deb9ac34..49e5f59b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -Version 2.13.0.9 (dev) not released yet (2025-01-15) +Version 2.13.0.9 (dev) not released yet (2025-01-18) ==================================================== **Incompatible changes** @@ -72,6 +72,8 @@ Bugs - library: need to check for valid UTF-8 after de-escaping - MAXICODE: maintain current set between segments - MSYS2: fix stdout output on Windows under MSYS2 (mailing list, props Frank) +- DATAMATRIX: fix mis-encodation by only doing special end-of-data processing + on last segment Version 2.13.0 (2023-12-18) diff --git a/README.bsd b/README.bsd index b0465948..48cb6ea8 100644 --- a/README.bsd +++ b/README.bsd @@ -1,5 +1,5 @@ -% README.bsd 2024-01-17 -% Tested on FreeBSD 14.0-RELEASE (with X11 + GNOME installed), OpenBSD 7.4 (with X11) and NetBSD 9.3 (with X11) +% README.bsd 2025-01-18 +% Tested on FreeBSD 14.2-RELEASE (with X11 + GNOME installed), OpenBSD 7.6 (with X11) and NetBSD 10.0 (with X11) 1. Prerequisites for building zint ================================== @@ -74,7 +74,20 @@ and on NetBSD instead. -3. CMake options +4. Run +====== + +On FreeBSD and OpenBSD, the CLI zint and GUI zint-qt should run without issue from the command line. + +On NetBSD you may have to set LD_LIBRARY_PATH if using the default ksh. For zint ("libzint.so" and "libpng16.so") and +zint-qt (Qt5 libraries and "libGL.so"): + + setenv LD_LIBRARY_PATH /usr/local/lib:/usr/pkg/lib:/usr/pkg/qt5/lib:/usr/X11R7/lib + +Place in "~/.cshrc" to make permanent. + + +5. CMake options ================ See "README.linux". Note for running the test suite on FreeBSD, if using the default csh, to set LD_LIBRARY_PATH use: diff --git a/backend/dmatrix.c b/backend/dmatrix.c index 997d24ea..5ea4d303 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -1,7 +1,7 @@ /* dmatrix.c Handles Data Matrix ECC 200 symbols */ /* libzint - the open source barcode library - Copyright (C) 2009-2024 Robin Stuart + Copyright (C) 2009-2025 Robin Stuart developed from and including some functions from: IEC16022 bar code generation @@ -323,7 +323,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co const unsigned char c = source[sp]; const int is_extended = c & 0x80; - /* ascii ... step (l) */ + /* ASCII ... step (l) */ if (z_isdigit(c)) { ascii_count += DM_MULT_1_DIV_2; /* (l)(1) */ } else { @@ -334,7 +334,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co } } - /* c40 ... step (m) */ + /* C40 ... step (m) */ if (dm_isc40(c)) { c40_count += DM_MULT_2_DIV_3; /* (m)(1) */ } else { @@ -345,7 +345,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co } } - /* text ... step (n) */ + /* TEXT ... step (n) */ if (dm_istext(c)) { text_count += DM_MULT_2_DIV_3; /* (n)(1) */ } else { @@ -356,7 +356,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co } } - /* x12 ... step (o) */ + /* X12 ... step (o) */ if (dm_isX12(c)) { x12_count += DM_MULT_2_DIV_3; /* (o)(1) */ } else { @@ -367,7 +367,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co } } - /* edifact ... step (p) */ + /* EDIFACT ... step (p) */ if (dm_isedifact(c)) { edf_count += DM_MULT_3_DIV_4; /* (p)(1) */ } else { @@ -378,7 +378,7 @@ static int dm_look_ahead_test(const unsigned char source[], const int length, co } } - /* base 256 ... step (q) */ + /* Base 256 ... step (q) */ if (gs1 == 1 && c == '\x1D') { /* FNC1 separator */ b256_count += DM_MULT_4; /* (q)(1) */ @@ -740,19 +740,20 @@ static int dm_last_ascii(const unsigned char source[], const int length, const i /* Treat EDIFACT edges specially, returning DM_ASCII mode if not full (i.e. encoding < 4 chars), or if full and at EOD where 1 or 2 ASCII chars can be encoded */ -static int dm_getEndMode(struct zint_symbol *symbol, const unsigned char *source, const int length, const int mode, - const int from, const int len, const int size) { +static int dm_getEndMode(struct zint_symbol *symbol, const unsigned char *source, const int length, + const int last_seg, const int mode, const int from, const int len, const int size) { if (mode == DM_EDIFACT) { - int last_ascii; if (len < 4) { return DM_ASCII; } - last_ascii = dm_last_ascii(source, length, from + len); - if (last_ascii) { /* At EOD with remaining chars ASCII-encodable in 1 or 2 codewords */ - const int symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); - /* If no codewords left and 1 or 2 ASCII-encodables or 1 codeword left and 1 ASCII-encodable */ - if (symbols_left <= 2 - last_ascii) { - return DM_ASCII; + if (last_seg) { + const int last_ascii = dm_last_ascii(source, length, from + len); + if (last_ascii) { /* At EOD with remaining chars ASCII-encodable in 1 or 2 codewords */ + const int symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); + /* If no codewords left and 1 or 2 ASCII-encodables or 1 codeword left and 1 ASCII-encodable */ + if (symbols_left <= 2 - last_ascii) { + return DM_ASCII; + } } } } @@ -796,12 +797,11 @@ static int dm_getNumberOfC40Words(const unsigned char *source, const int length, } /* Initialize a new edge. Returns endMode */ -static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, const int length, +static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, const int length, const int last_seg, struct dm_edge *edges, const int mode, const int from, const int len, struct dm_edge *previous, struct dm_edge *edge, const int cwds) { int previousMode; int size; - int last_ascii, symbols_left; edge->mode = mode; edge->endMode = mode; @@ -859,9 +859,9 @@ static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, size++; /* Unlatch to ASCII */ } } - if (from + len + 2 >= length) { /* If less than batch of 3 away from EOD */ - last_ascii = dm_last_ascii(source, length, from + len); - symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); + if (last_seg && from + len + 2 >= length) { /* If less than batch of 3 away from EOD */ + const int last_ascii = dm_last_ascii(source, length, from + len); + const int symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); if (symbols_left > 0) { size++; /* We need an extra unlatch at the end */ } @@ -877,12 +877,12 @@ static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, size++; /* Unlatch to ASCII */ } } - if (from + len + 2 >= length) { /* If less than batch of 3 away from EOD */ - last_ascii = dm_last_ascii(source, length, from + len); + if (last_seg && from + len + 2 >= length) { /* If less than batch of 3 away from EOD */ + const int last_ascii = dm_last_ascii(source, length, from + len); if (last_ascii == 2) { /* Only 1 ASCII-encodable allowed at EOD for X12, unlike C40/TEXT */ size++; /* We need an extra unlatch at the end */ } else { - symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); + const int symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0); if (symbols_left > 0) { size++; /* We need an extra unlatch at the end */ } @@ -898,7 +898,7 @@ static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, size++; /* Unlatch to ASCII */ } } - edge->endMode = dm_getEndMode(symbol, source, length, mode, from, len, size); + edge->endMode = dm_getEndMode(symbol, source, length, last_seg, mode, from, len, size); break; } edge->size = size; @@ -907,11 +907,11 @@ static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, } /* Add an edge for a mode at a vertex if no existing edge or if more optimal than existing edge */ -static void dm_addEdge(struct zint_symbol *symbol, const unsigned char *source, const int length, +static void dm_addEdge(struct zint_symbol *symbol, const unsigned char *source, const int length, const int last_seg, struct dm_edge *edges, const int mode, const int from, const int len, struct dm_edge *previous, const int cwds) { struct dm_edge edge; - const int endMode = dm_new_Edge(symbol, source, length, edges, mode, from, len, previous, &edge, cwds); + const int endMode = dm_new_Edge(symbol, source, length, last_seg, edges, mode, from, len, previous, &edge, cwds); const int vertexIndex = from + len; const int v_ij = vertexIndex * DM_NUM_MODES + endMode - 1; @@ -925,7 +925,7 @@ static void dm_addEdge(struct zint_symbol *symbol, const unsigned char *source, /* Add edges for the various modes at a vertex */ static void dm_addEdges(struct zint_symbol *symbol, const unsigned char source[], const int length, - struct dm_edge *edges, const int from, struct dm_edge *previous, const int gs1) { + const int last_seg, struct dm_edge *edges, const int from, struct dm_edge *previous, const int gs1) { int i, pos; /* Not possible to unlatch a full EDF edge to something else */ @@ -934,29 +934,29 @@ static void dm_addEdges(struct zint_symbol *symbol, const unsigned char source[] static const char c40text_modes[] = { DM_C40, DM_TEXT }; if (z_isdigit(source[from]) && from + 1 < length && z_isdigit(source[from + 1])) { - dm_addEdge(symbol, source, length, edges, DM_ASCII, from, 2, previous, 0); + dm_addEdge(symbol, source, length, last_seg, edges, DM_ASCII, from, 2, previous, 0); /* If ASCII vertex, don't bother adding other edges as this will be optimal; suggested by Alex Geller */ if (previous && previous->mode == DM_ASCII) { return; } } else { - dm_addEdge(symbol, source, length, edges, DM_ASCII, from, 1, previous, 0); + dm_addEdge(symbol, source, length, last_seg, edges, DM_ASCII, from, 1, previous, 0); } for (i = 0; i < ARRAY_SIZE(c40text_modes); i++) { int len; int cwds = dm_getNumberOfC40Words(source, length, from, c40text_modes[i], &len); if (cwds) { - dm_addEdge(symbol, source, length, edges, c40text_modes[i], from, len, previous, cwds); + dm_addEdge(symbol, source, length, last_seg, edges, c40text_modes[i], from, len, previous, cwds); } } if (from + 2 < length && dm_isX12(source[from]) && dm_isX12(source[from + 1]) && dm_isX12(source[from + 2])) { - dm_addEdge(symbol, source, length, edges, DM_X12, from, 3, previous, 0); + dm_addEdge(symbol, source, length, last_seg, edges, DM_X12, from, 3, previous, 0); } if (gs1 != 1 || source[from] != '\x1D') { - dm_addEdge(symbol, source, length, edges, DM_BASE256, from, 1, previous, 0); + dm_addEdge(symbol, source, length, last_seg, edges, DM_BASE256, from, 1, previous, 0); } } @@ -964,14 +964,14 @@ static void dm_addEdges(struct zint_symbol *symbol, const unsigned char source[] /* We create 3 EDF edges, 2, 3 or 4 characters length. The 4-char normally doesn't have a latch to ASCII unless it is 2 characters away from the end of the input. */ for (i = 1, pos = from + i; i < 4 && pos < length && dm_isedifact(source[pos]); i++, pos++) { - dm_addEdge(symbol, source, length, edges, DM_EDIFACT, from, i + 1, previous, 0); + dm_addEdge(symbol, source, length, last_seg, edges, DM_EDIFACT, from, i + 1, previous, 0); } } } /* Calculate optimized encoding modes */ static int dm_define_mode(struct zint_symbol *symbol, char modes[], const unsigned char source[], const int length, - const int gs1, const int debug_print) { + const int last_seg, const int gs1, const int debug_print) { int i, j, v_i; int minimalJ, minimalSize; @@ -983,7 +983,7 @@ static int dm_define_mode(struct zint_symbol *symbol, char modes[], const unsign if (!edges) { return 0; } - dm_addEdges(symbol, source, length, edges, 0, NULL, gs1); + dm_addEdges(symbol, source, length, last_seg, edges, 0, NULL, gs1); DM_TRACE_Edges("DEBUG Initial situation\n", source, length, edges, 0); @@ -991,7 +991,7 @@ static int dm_define_mode(struct zint_symbol *symbol, char modes[], const unsign v_i = i * DM_NUM_MODES; for (j = 0; j < DM_NUM_MODES; j++) { if (edges[v_i + j].mode) { - dm_addEdges(symbol, source, length, edges, i, edges + v_i + j, gs1); + dm_addEdges(symbol, source, length, last_seg, edges, i, edges + v_i + j, gs1); } } DM_TRACE_Edges("DEBUG situation after adding edges to vertices at position %d\n", source, length, edges, i); @@ -1046,20 +1046,19 @@ static int dm_define_mode(struct zint_symbol *symbol, char modes[], const unsign } /* Do default minimal encodation */ -static int dm_minimalenc(struct zint_symbol *symbol, const unsigned char source[], const int length, int *p_sp, - unsigned char target[], int *p_tp, int process_buffer[8], int *p_process_p, int *p_b256_start, - int *p_current_mode, const int gs1, const int debug_print) { +static int dm_minimalenc(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int last_seg, int *p_sp, unsigned char target[], int *p_tp, int process_buffer[8], int *p_process_p, + int *p_b256_start, int *p_current_mode, const int gs1, const int debug_print) { int sp = *p_sp; int tp = *p_tp; int process_p = *p_process_p; int current_mode = *p_current_mode; - int last_ascii, symbols_left; int i; char *modes = (char *) z_alloca(length); assert(length <= 10921); /* Can only handle (10921 + 1) * 6 = 65532 < 65536 (2*16) due to sizeof(previous) */ - if (!dm_define_mode(symbol, modes, source, length, gs1, debug_print)) { + if (!dm_define_mode(symbol, modes, source, length, last_seg, gs1, debug_print)) { return errtxt(ZINT_ERROR_MEMORY, symbol, 728, "Insufficient memory for mode buffers"); } @@ -1074,17 +1073,19 @@ static int dm_minimalenc(struct zint_symbol *symbol, const unsigned char source[ target[tp++] = 254; /* Unlatch */ break; case DM_EDIFACT: - last_ascii = dm_last_ascii(source, length, sp); - if (!last_ascii) { - process_buffer[process_p++] = 31; /* Unlatch */ - } else { - symbols_left = dm_codewords_remaining(symbol, tp + last_ascii, process_p); - if (debug_print) { - printf("process_p %d, last_ascii %d, symbols_left %d\n", - process_p, last_ascii, symbols_left); - } - if (symbols_left > 2 - last_ascii) { + if (last_seg) { + const int last_ascii = dm_last_ascii(source, length, sp); + if (!last_ascii) { process_buffer[process_p++] = 31; /* Unlatch */ + } else { + const int symbols_left = dm_codewords_remaining(symbol, tp + last_ascii, process_p); + if (debug_print) { + printf("process_p %d, last_ascii %d, symbols_left %d, last_seg %d\n", + process_p, last_ascii, symbols_left, last_seg); + } + if (symbols_left > 2 - last_ascii) { + process_buffer[process_p++] = 31; /* Unlatch */ + } } } process_p = dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 1 /*empty*/, debug_print); @@ -1251,7 +1252,7 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c next_mode = DM_C40; tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print); while (sp < 45) { - assert(!(sp & 0x80)); + assert(dm_isc40(source[sp])); process_buffer[process_p++] = dm_c40_value[source[sp]]; if (process_p >= 3) { @@ -1488,7 +1489,7 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c /* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate Supports encoding FNC1 in supporting systems */ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci, - const int gs1, unsigned char target[], int *p_tp) { + const int last_seg, const int gs1, unsigned char target[], int *p_tp) { int sp = 0; int tp = *p_tp; int current_mode = DM_ASCII; @@ -1521,23 +1522,23 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c error_number = dm_isoenc(symbol, source, length, &sp, target, &tp, process_buffer, &process_p, &b256_start, ¤t_mode, gs1, debug_print); } else { /* Do default minimal encodation */ - error_number = dm_minimalenc(symbol, source, length, &sp, target, &tp, process_buffer, &process_p, + error_number = dm_minimalenc(symbol, source, length, last_seg, &sp, target, &tp, process_buffer, &process_p, &b256_start, ¤t_mode, gs1, debug_print); } if (error_number != 0) { return error_number; } - symbols_left = dm_codewords_remaining(symbol, tp, process_p); + symbols_left = last_seg ? dm_codewords_remaining(symbol, tp, process_p) : 3; - if (debug_print) printf("\nsymbols_left %d, tp %d, process_p %d ", symbols_left, tp, process_p); + if (debug_print) printf("\nsymbols_left %d, tp %d, process_p %d, last_seg %d, ", symbols_left, tp, process_p, last_seg); if (current_mode == DM_C40 || current_mode == DM_TEXT) { /* NOTE: changed to follow spec exactly here, only using Shift 1 padded triplets when 2 symbol chars remain. - This matches the behaviour of BWIPP but not tec-it, nor figures 4.15.1-1 and 4.15-1-2 in GS1 General + This matches the behaviour of BWIPP but not TEC-IT, nor figures 4.15.1-1 and 4.15-1-2 in GS1 General Specifications 21.0.1. */ - if (debug_print) printf("%s ", current_mode == DM_C40 ? "C40" : "TEX"); + if (debug_print) fputs(current_mode == DM_C40 ? "C40 " : "TEX ", stdout); if (process_p == 0) { if (symbols_left > 0) { target[tp++] = 254; /* Unlatch */ @@ -1553,7 +1554,7 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c /* 5.2.5.2 (c)/(d) */ if (symbols_left > 1) { /* 5.2.5.2 (c) */ - target[tp++] = 254; /* Unlatch and encode remaining data in ascii. */ + target[tp++] = 254; /* Unlatch and encode remaining data in ASCII. */ if (debug_print) fputs("ASC ", stdout); } target[tp++] = source[length - 1] + 1; @@ -1568,7 +1569,6 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c total_cnt += cnt; process_p -= cnt; } - if (debug_print) printf("Mode %d, backtracked %d\n", current_mode, (total_cnt / 3) * 2); tp -= (total_cnt / 3) * 2; target[tp++] = 254; /* Unlatch */ @@ -1632,7 +1632,7 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c if (debug_print) printf("A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1); } } else { - /* Append edifact unlatch value (31) and empty buffer */ + /* Append EDIFACT unlatch value (31) and empty buffer */ if (process_p <= 3) { process_buffer[process_p++] = 31; } @@ -1665,8 +1665,8 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c #ifdef ZINT_TEST /* Wrapper for direct testing */ INTERNAL int dm_encode_test(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci, - const int gs1, unsigned char target[], int *p_tp) { - return dm_encode(symbol, source, length, eci, gs1, target, p_tp); + const int last_seg, const int gs1, unsigned char target[], int *p_tp) { + return dm_encode(symbol, source, length, eci, last_seg, gs1, target, p_tp); } #endif @@ -1803,8 +1803,8 @@ static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], co len_dec += 2; /* Remove RS + EOT from end */ } } - error_number = dm_encode(symbol, segs[i].source + src_inc, segs[i].length - len_dec, segs[i].eci, gs1, - target, &tp); + error_number = dm_encode(symbol, segs[i].source + src_inc, segs[i].length - len_dec, segs[i].eci, + i + 1 == seg_count, gs1, target, &tp); if (error_number != 0) { return error_number; } @@ -1874,7 +1874,7 @@ static int dm_ecc200(struct zint_symbol *symbol, struct zint_seg segs[], const i dm_add_tail(binary, binlen, taillength); } if (debug_print) { - printf("Pads (%d): ", taillength); + printf("HxW: %dx%d\nPads (%d): ", H, W, taillength); for (i = binlen; i < binlen + taillength; i++) printf("%d ", binary[i]); fputc('\n', stdout); } diff --git a/backend/dxfilmedge.c b/backend/dxfilmedge.c index dd76f9ec..868d6f89 100644 --- a/backend/dxfilmedge.c +++ b/backend/dxfilmedge.c @@ -1,7 +1,7 @@ /* dxfilmedge.c - Handles DX Film Edge symbology */ /* libzint - the open source barcode library - Copyright (C) 2024 Antoine Merino + Copyright (C) 2024-2025 Antoine Merino Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -45,10 +45,10 @@ #include "common.h" #define DX_DEBUG_STR_LEN 20 -/* Max length of the DX info part. Include the \0. Eg: "018500\0", "150-10\0" */ +/* Max length of the DX info part. Eg: "018500", "150-10" */ #define DX_MAX_DX_INFO_LENGTH 6 #define DX_MAX_DX_INFO_MAX_STR "6" /* String version of above */ -/* Max length of the frame info part. Eg: "00A\0", "23A\0" */ +/* Max length of the frame info part. Eg: "00A", "23A" */ #define DX_MAX_FRAME_INFO_LENGTH 3 #define DX_MAX_FRAME_INFO_MAX_STR "3" /* String version of above */ @@ -132,7 +132,7 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source } if (sscanf(dx_info, "%d-%d", &dx_code_1, &dx_code_2) < 2) { return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 977, - "Wrong format for DX parts 1 and 2 (expected format: XXX-XX, digits)"); + "Wrong format for DX parts 1 and 2 (expected format: NNN-NN, digits)"); } if (dx_code_1 <= 0 || dx_code_1 > 127) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 978, "DX part 1 \"%d\" out of range (1 to 127)", diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index 6fe1be09..06464e0a 100644 --- a/backend/tests/test_codablock.c +++ b/backend/tests/test_codablock.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019-2024 Robin Stuart + Copyright (C) 2019-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -332,8 +332,14 @@ static void test_input(const testCtx *const p_ctx) { /* 42*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, -1, "ÿ12345678\012à12345678abcdef\0121\01223456\012\0127890àAàBCDEFà\012\012à", -1, 0, 8, 134, 0, "(96) 67 64 46 64 5F 63 0C 22 38 4E 5E 6A 67 62 0B 4A 64 64 40 63 0C 22 2B 6A 67 63 2C 38", "BWIPP different encoding (CodeB before FNC4 instead of after)" }, /* 43*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, -1, "123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé12345123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2" "B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé6789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890àààààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\012123456à\012à\012à\0123Ä4Ä5Ä6AÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécéÄÄÄÄÄÄ2ÄÄÄÄÄÄÄÄ4ÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécéÄÄÄAÄÄÄÄÄÄaÄÄÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé", -1, 0, 44, 739, 0, "(2948) 67 63 2A 0C 22 38 4E 5A 0C 22 65 15 21 22 23 24 25 26 27 28 29 4A 63 0C 22 38 64", "BWIPP gs command too long" }, /* 44*/ { BARCODE_CODABLOCKF, UNICODE_MODE, -1, -1, "ÿ12345678\012à12345678abcdef\012\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890ààààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄÄÄÄÄ2ÄÄÄÄÄÄ4ÄÄÄÄÄÄaÄÄÄÄé1é2é34é56Ä78é9éAéBéCéééééaébécé123456789012345ABCDEFGHI\012123456ÿ12345678\012à12345678abcdef\012123456\012\0127890àABCDEFà\012\012ààGHIJKàLMNOPQabc\012defà1234567ghijk\012\012à901234\0122567890àààààABCDEFGààà\012\012\012HIJK\012\012\0122à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2B3C4a5b6c7d8e9\0120\0121\0122\0123Ä4Ä5Ä6A7a8A9a0\012Ä12345678ÄÄ2Ä4ÄaÄé1é2é34é56Ä78é9éAéBéCééaébécé123456789012345ABCDEF\012123456ÿ123456\012à12345678abcdef\012\0121234\012\0127890àABCDà\012\012ààGHIJKàLMabc\012defà1234567ghijk\012\012à901234\012\012\012\012567890ààABCDEFGààà\012\012\012HIJK\012\012\012\012à\012à\012à\01212345à\012à\012à67890ààÄ9012ÄÄ56789Ä12Ä3\0124\0125\0126A\012a\012A\012A\012a\012a\012BCD1A2", -1, 0, 33, 387, 0, "(1155) 67 64 5F 64 5F 63 0C 22 38 4E 65 4A 64 64 40 63 0C 22 38 4E 64 41 42 43 44 45 46", "BWIPP different encodation" }, - /* 45*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, -1, -1, "A99912345/$$52001510X3", -1, 0, 6, 101, 1, "(54) 67 64 44 0B 21 19 19 3A 6A 67 63 2B 5B 17 2D 64 24 6A 67 64 0C 0F 04 04 15 16 6A 67", "" }, - /* 46*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, -1, -1, "A99912345/$$520:1510X3", -1, ZINT_ERROR_INVALID_DATA, -1, -1, 1, "Error 203: Invalid character at position 16 in input (alphanumerics, space and \"-.$/+%\" only)", "" }, + /* 45*/ { BARCODE_CODABLOCKF, DATA_MODE | ESCAPE_MODE, -1, -1, "\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09", -1, 0, 3, 101, 1, "67 62 41 41 42 43 44 5B 6A 67 62 0B 45 46 47 48 37 6A 67 62 0C 49 63 1B 44 2C 6A", "Okapi control-chars-1.png" }, + /* 46*/ { BARCODE_CODABLOCKF, DATA_MODE | ESCAPE_MODE, 4, -1, "\\x80\\x81\\x82\\x83\\x9E\\x9F\\xA0", -1, 0, 4, 101, 1, "(36) 67 62 42 65 40 65 41 24 6A 67 62 0B 65 42 65 43 31 6A 67 62 0C 65 5E 65 5F 16 6A 67", "Okapi control-chars-2.png" }, + /* 47*/ { BARCODE_CODABLOCKF, DATA_MODE | ESCAPE_MODE, -1, -1, "\\x00z", -1, 0, 2, 101, 0, "67 62 40 40 62 5A 63 00 6A 67 64 0B 63 64 32 04 3F 6A", "Okapi data-null-z.png; BWIPP different encodation" }, + /* 48*/ { BARCODE_CODABLOCKF, UNICODE_MODE | ESCAPE_MODE, -1, -1, "2610\\u00F2", -1, 0, 2, 101, 1, "67 63 00 1A 0A 64 63 4B 6A 67 64 0B 64 52 33 26 64 6A", "Okapi data-fuzz-19.png" }, + /* 49*/ { BARCODE_CODABLOCKF, DATA_MODE | ESCAPE_MODE, 7, -1, "*\\r\\xF2\\x82\\x82(\\x982\\x82\\x82*\\r\\xF2\\x82\\xA8\\x82\\x82\\x82\\x82", -1, 0, 7, 123, 0, "(77) 67 62 45 0A 4D 64 64 52 63 35 6A 67 62 0B 65 42 65 42 08 63 43 6A 67 62 0C 65 58 12", "Okapi data-fuzz-20.png; BWIPP different encodation" }, + /* 50*/ { BARCODE_CODABLOCKF, UNICODE_MODE | ESCAPE_MODE, -1, -1, "\\u0018\\u00F2", -1, 0, 2, 101, 0, "67 62 40 58 65 62 52 16 6A 67 64 0B 63 64 38 30 30 6A", "Okapi data-fuzz-21.png; BWIPP different encodation" }, + /* 51*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, -1, -1, "A99912345/$$52001510X3", -1, 0, 6, 101, 1, "(54) 67 64 44 0B 21 19 19 3A 6A 67 63 2B 5B 17 2D 64 24 6A 67 64 0C 0F 04 04 15 16 6A 67", "" }, + /* 52*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, -1, -1, "A99912345/$$520:1510X3", -1, ZINT_ERROR_INVALID_DATA, -1, -1, 1, "Error 203: Invalid character at position 16 in input (alphanumerics, space and \"-.$/+%\" only)", "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_dmatrix.c b/backend/tests/test_dmatrix.c index 3970b62c..5d8a7f0b 100644 --- a/backend/tests/test_dmatrix.c +++ b/backend/tests/test_dmatrix.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019-2024 Robin Stuart + Copyright (C) 2019-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -358,7 +358,12 @@ static void test_large(const testCtx *const p_ctx) { struct zint_symbol *symbol = NULL; char data_buf[ZINT_MAX_DATA_LEN]; - char escaped[64]; + + char escaped[8192]; + char cmp_buf[32768]; + char cmp_msg[1024]; + + int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); /* Only do ZXing-C++ test if asked, too slow otherwise */ testStartSymbol("test_large", &symbol); @@ -387,6 +392,7 @@ static void test_large(const testCtx *const p_ctx) { data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, testUtilEscape(data[i].pattern, (int) strlen(data[i].pattern), escaped, sizeof(escaped)), data[i].length, testUtilErrorName(ret), symbol->rows, symbol->width, errtxt); + ZBarcode_Clear(symbol); symbol->input_mode |= FAST_MODE; (void) ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); printf(" \"%s\", \"%s\" },\n", strcmp(errtxt, symbol->errtxt) != 0 ? symbol->errtxt : "", data[i].comment); @@ -398,8 +404,20 @@ static void test_large(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data_buf, length, debug)) { + int cmp_len, ret_len; + char modules_dump[144 * 144 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, data_buf, 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_buf, 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); + } } + ZBarcode_Clear(symbol); symbol->input_mode |= FAST_MODE; ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); @@ -408,6 +426,17 @@ static void test_large(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data_buf, length, debug)) { + int cmp_len, ret_len; + char modules_dump[144 * 144 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, data_buf, 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_buf, 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); + } } else { if (data[i].expected_errtxt2[0]) { assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt2), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt2); @@ -433,17 +462,25 @@ static void test_buffer(const testCtx *const p_ctx) { int output_options; char *data; int ret; + int bwipp_cmp; char *comment; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { 16383, UNICODE_MODE, READER_INIT, "1", 0, "" }, - /* 1*/ { 3, UNICODE_MODE, 0, "000106j 05 Galeria A Nação0000000000", 0, "From Okapi, consecutive use of upper shift; #176" }, + /* 0*/ { 16383, UNICODE_MODE, READER_INIT, "1", 0, 1, "" }, + /* 1*/ { 3, UNICODE_MODE, 0, "000106j 05 Galeria A Nação0000000000", 0, 0, "From Okapi, consecutive use of upper shift; #176; BWIPP different encodation" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + char escaped[8192]; + char cmp_buf[32768]; + 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_buffer", &symbol); for (i = 0; i < data_size; i++) { @@ -457,6 +494,31 @@ static void test_buffer(const testCtx *const p_ctx) { ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); + 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[144 * 144 + 1]; + 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[144 * 144 + 1]; + 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); + } ZBarcode_Delete(symbol); } @@ -481,114 +543,123 @@ static void test_options(const testCtx *const p_ctx) { int expected_rows; int expected_width; const char *expected_errtxt; + int bwipp_cmp; + const char *comment; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "" }, - /* 1*/ { BARCODE_DATAMATRIX, -1, 2, -1, -1, -1, { 0, 0, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 524: Older Data Matrix standards are no longer supported" }, - /* 2*/ { BARCODE_DATAMATRIX, -1, -1, 1, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "" }, - /* 3*/ { BARCODE_DATAMATRIX, -1, -1, 2, -1, -1, { 0, 0, "" }, "1", 0, 12, 12, "" }, - /* 4*/ { BARCODE_DATAMATRIX, -1, -1, 48, -1, -1, { 0, 0, "" }, "1", 0, 26, 64, "" }, - /* 5*/ { BARCODE_DATAMATRIX, -1, -1, 49, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "" }, /* Ignored */ - /* 6*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____", 0, 12, 12, "" }, /* 4 data */ - /* 7*/ { BARCODE_DATAMATRIX, -1, -1, 1, -1, -1, { 0, 0, "" }, "____", ZINT_ERROR_TOO_LONG, -1, -1, "Error 522: Input too long for Version 1, requires 4 codewords (maximum 3)" }, - /* 8*/ { BARCODE_DATAMATRIX, -1, -1, 25, -1, -1, { 0, 0, "" }, "____", 0, 8, 18, "" }, - /* 9*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________", 0, 8, 32, "" }, /* 10 data */ - /* 10*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________", 0, 8, 32, "" }, - /* 11*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE | DM_ISO_144, -1, { 0, 0, "" }, "__________", 0, 8, 32, "" }, - /* 12*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________", 0, 16, 16, "" }, - /* 13*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE | DM_ISO_144, -1, { 0, 0, "" }, "__________", 0, 16, 16, "" }, - /* 14*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________", 0, 12, 26, "" }, /* 15 data */ - /* 15*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________", 0, 12, 26, "" }, - /* 16*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________", 0, 18, 18, "" }, - /* 17*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________", 0, 18, 18, "" }, /* 18 data */ - /* 18*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________", 0, 20, 20, "" }, /* 19 data */ - /* 19*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________", 0, 20, 20, "" }, /* 21 data */ - /* 20*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________", 0, 22, 22, "" }, /* 23 data */ - /* 21*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________", 0, 8, 64, "" }, - /* 22*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________", 0, 22, 22, "" }, - /* 23*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________", 0, 16, 36, "" }, /* 31 data */ - /* 24*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________", 0, 16, 36, "" }, - /* 25*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________", 0, 24, 24, "" }, - /* 26*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________", 0, 26, 26, "" }, /* 37 data */ - /* 27*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_____________________________________", 0, 8, 96, "" }, - /* 28*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_____________________________________", 0, 26, 26, "" }, - /* 29*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________", 0, 26, 26, "" }, /* 39 data */ - /* 30*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________", 0, 12, 64, "" }, - /* 31*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________", 0, 26, 26, "" }, - /* 32*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________________________________", 0, 26, 26, "" }, /* 43 data */ - /* 33*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "___________________________________________", 0, 12, 64, "" }, - /* 34*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "___________________________________________", 0, 26, 26, "" }, - /* 35*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____________________________________________", 0, 26, 26, "" }, /* 44 data */ - /* 36*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________________", 0, 16, 48, "" }, /* 45 data */ - /* 37*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_____________________________________________", 0, 16, 48, "" }, - /* 38*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_____________________________________________", 0, 32, 32, "" }, - /* 39*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_________________________________________________", 0, 16, 48, "" }, /* 49 data */ - /* 40*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_________________________________________________", 0, 16, 48, "" }, - /* 41*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_________________________________________________", 0, 32, 32, "" }, - /* 42*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________________________________________", 0, 32, 32, "" }, /* 50 data */ - /* 43*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________________________________________________", 0, 20, 44, "" }, - /* 44*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________________________________________________", 0, 32, 32, "" }, - /* 45*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 32, 32, "" }, /* 51 data */ - /* 46*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 20, 44, "" }, - /* 47*/ { BARCODE_DATAMATRIX, -1, -1, -1, 9999, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 32, 32, "" }, /* Ignored */ - /* 48*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________________________________", 0, 32, 32, "" }, /* 61 data */ - /* 49*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________", 0, 32, 32, "" }, /* 62 data */ - /* 50*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 36, 36, "" }, /* 63 data */ - /* 51*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 8, 144, "" }, - /* 52*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 36, 36, "" }, - /* 53*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "________________________________________________________________", 0, 36, 36, "" }, /* 64 data */ - /* 54*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "________________________________________________________________", 0, 12, 88, "" }, - /* 55*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "________________________________________________________________", 0, 36, 36, "" }, - /* 56*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 36, 36, "" }, /* 65 data */ - /* 57*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 26, 40, "" }, - /* 58*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 36, 36, "" }, - /* 59*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 36, 36, "" }, /* 70 data */ - /* 60*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 26, 40, "" }, - /* 61*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 36, 36, "" }, - /* 62*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 36, 36, "" }, /* 71 data */ - /* 63*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 22, 48, "" }, - /* 64*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 36, 36, "" }, - /* 65*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 36, 36, "" }, /* 80 data */ - /* 66*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 24, 48, "" }, - /* 67*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 36, 36, "" }, - /* 68*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 36, 36, "" }, /* 84 data */ - /* 69*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 20, 64, "" }, - /* 70*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 36, 36, "" }, - /* 71*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 40, 40, "" }, /* 90 data */ - /* 72*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 26, 48, "" }, - /* 73*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 40, 40, "" }, - /* 74*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 40, 40, "" }, /* 91 data */ - /* 75*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 24, 64, "" }, - /* 76*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 40, 40, "" }, - /* 77*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 44, 44, "" }, /* 118 data */ - /* 78*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 26, 64, "" }, /* 118 data */ - /* 79*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 44, 44, "" }, /* 118 data */ - /* 80*/ { BARCODE_DATAMATRIX, GS1_MODE, -1, -1, -1, -1, { 0, 0, "" }, "[90]12", 0, 10, 10, "" }, - /* 81*/ { BARCODE_DATAMATRIX, GS1_MODE | GS1PARENS_MODE, -1, -1, -1, -1, { 0, 0, "" }, "(90)12", 0, 10, 10, "" }, - /* 82*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 2, "" }, "1", 0, 12, 12, "" }, - /* 83*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 16, 16, "" }, "1", 0, 12, 12, "" }, - /* 84*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 1, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 720: Structured Append count '1' out of range (2 to 16)" }, - /* 85*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 17, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 720: Structured Append count '17' out of range (2 to 16)" }, - /* 86*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 16, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 721: Structured Append index '0' out of range (1 to count 16)" }, - /* 87*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 17, 16, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 721: Structured Append index '17' out of range (1 to count 16)" }, - /* 88*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1001" }, "1", 0, 12, 12, "" }, - /* 89*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "A" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 723: Invalid Structured Append ID (digits only)" }, - /* 90*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "0" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 724: Structured Append ID1 '000' and ID2 '000' out of range (001 to 254) (ID \"000000\")" }, - /* 91*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 725: Structured Append ID1 '000' out of range (001 to 254) (ID \"000001\")" }, - /* 92*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1000" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 726: Structured Append ID2 '000' out of range (001 to 254) (ID \"001000\")" }, - /* 93*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "001255" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 726: Structured Append ID2 '255' out of range (001 to 254) (ID \"001255\")" }, - /* 94*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "255001" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 725: Structured Append ID1 '255' out of range (001 to 254) (ID \"255001\")" }, - /* 95*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "255255" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 724: Structured Append ID1 '255' and ID2 '255' out of range (001 to 254) (ID \"255255\")" }, - /* 96*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1234567" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 722: Structured Append ID length 7 too long (6 digit maximum)" }, - /* 97*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, READER_INIT, { 2, 3, "1001" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 727: Cannot have Structured Append and Reader Initialisation at the same time" }, - /* 98*/ { BARCODE_DATAMATRIX, ESCAPE_MODE, -1, -1, -1, -1, { 2, 3, "1001" }, "[)>\\R05\\GA\\R\\E", 0, 12, 26, "" }, /* Macro05/06 ignored if have Structured Append TODO: error/warning */ - /* 99*/ { BARCODE_HIBC_DM, -1, -1, -1, -1, -1, { 0, 0, "" }, "1234,67", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 5 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 0*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "", 1, "" }, + /* 1*/ { BARCODE_DATAMATRIX, -1, 2, -1, -1, -1, { 0, 0, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 524: Older Data Matrix standards are no longer supported", 1, "" }, + /* 2*/ { BARCODE_DATAMATRIX, -1, -1, 1, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "", 1, "" }, + /* 3*/ { BARCODE_DATAMATRIX, -1, -1, 2, -1, -1, { 0, 0, "" }, "1", 0, 12, 12, "", 1, "" }, + /* 4*/ { BARCODE_DATAMATRIX, -1, -1, 48, -1, -1, { 0, 0, "" }, "1", 0, 26, 64, "", 1, "" }, + /* 5*/ { BARCODE_DATAMATRIX, -1, -1, 49, -1, -1, { 0, 0, "" }, "1", 0, 10, 10, "", 0, "Ignored; BWIPP no options set" }, + /* 6*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____", 0, 12, 12, "", 1, "4 data" }, + /* 7*/ { BARCODE_DATAMATRIX, -1, -1, 1, -1, -1, { 0, 0, "" }, "____", ZINT_ERROR_TOO_LONG, -1, -1, "Error 522: Input too long for Version 1, requires 4 codewords (maximum 3)", 1, "" }, + /* 8*/ { BARCODE_DATAMATRIX, -1, -1, 25, -1, -1, { 0, 0, "" }, "____", 0, 8, 18, "", 1, "" }, + /* 9*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________", 0, 8, 32, "", 1, "10 data" }, + /* 10*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________", 0, 8, 32, "", 1, "" }, + /* 11*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE | DM_ISO_144, -1, { 0, 0, "" }, "__________", 0, 8, 32, "", 1, "" }, + /* 12*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________", 0, 16, 16, "", 1, "" }, + /* 13*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE | DM_ISO_144, -1, { 0, 0, "" }, "__________", 0, 16, 16, "", 1, "" }, + /* 14*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________", 0, 12, 26, "", 1, "15 data" }, + /* 15*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________", 0, 12, 26, "", 1, "" }, + /* 16*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________", 0, 18, 18, "", 1, "" }, + /* 17*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________", 0, 18, 18, "", 1, "18 data" }, + /* 18*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________", 0, 20, 20, "", 1, "19 data" }, + /* 19*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________", 0, 20, 20, "", 1, "21 data" }, + /* 20*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________", 0, 22, 22, "", 1, "23 data" }, + /* 21*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________", 0, 8, 64, "", 1, "" }, + /* 22*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________", 0, 22, 22, "", 1, "" }, + /* 23*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________", 0, 16, 36, "", 1, "31 data" }, + /* 24*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________", 0, 16, 36, "", 0, "BWIPP DMRE requires dimensions" }, + /* 25*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________", 0, 24, 24, "", 1, "" }, + /* 26*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________", 0, 26, 26, "", 1, "37 data" }, + /* 27*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_____________________________________", 0, 8, 96, "", 1, "" }, + /* 28*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_____________________________________", 0, 26, 26, "", 1, "" }, + /* 29*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________", 0, 26, 26, "", 1, "39 data" }, + /* 30*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________", 0, 12, 64, "", 1, "" }, + /* 31*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________", 0, 26, 26, "", 1, "" }, + /* 32*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________________________________", 0, 26, 26, "", 1, "43 data" }, + /* 33*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "___________________________________________", 0, 12, 64, "", 1, "" }, + /* 34*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "___________________________________________", 0, 26, 26, "", 1, "" }, + /* 35*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____________________________________________", 0, 26, 26, "", 1, "44 data" }, + /* 36*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________________", 0, 16, 48, "", 1, "45 data" }, + /* 37*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_____________________________________________", 0, 16, 48, "", 0, "BWIPP DMRE requires dimensions" }, + /* 38*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_____________________________________________", 0, 32, 32, "", 1, "" }, + /* 39*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_________________________________________________", 0, 16, 48, "", 1, "49 data" }, + /* 40*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_________________________________________________", 0, 16, 48, "", 0, "BWIPP DMRE requires dimensions" }, + /* 41*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_________________________________________________", 0, 32, 32, "", 1, "" }, + /* 42*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________________________________________", 0, 32, 32, "", 1, "50 data" }, + /* 43*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________________________________________________", 0, 20, 44, "", 1, "" }, + /* 44*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________________________________________________", 0, 32, 32, "", 1, "" }, + /* 45*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 32, 32, "", 0, "51 data; BWIPP different encodation" }, + /* 46*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 20, 44, "", 0, "BWIPP DMRE requires dimensions" }, + /* 47*/ { BARCODE_DATAMATRIX, -1, -1, -1, 9999, -1, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU", 0, 32, 32, "", 0, "Ignored; BWIPP different encodation" }, + /* 48*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_____________________________________________________________", 0, 32, 32, "", 1, "61 data" }, + /* 49*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________", 0, 32, 32, "", 1, "62 data" }, + /* 50*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 36, 36, "", 1, "63 data" }, + /* 51*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 8, 144, "", 1, "" }, + /* 52*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 53*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "________________________________________________________________", 0, 36, 36, "", 1, "64 data" }, + /* 54*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "________________________________________________________________", 0, 12, 88, "", 1, "" }, + /* 55*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 56*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 36, 36, "", 1, "65 data" }, + /* 57*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 26, 40, "", 1, "" }, + /* 58*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 59*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 36, 36, "", 1, "70 data" }, + /* 60*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 26, 40, "", 1, "" }, + /* 61*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "______________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 62*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 36, 36, "", 1, "71 data" }, + /* 63*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 22, 48, "", 1, "" }, + /* 64*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "_______________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 65*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 36, 36, "", 1, "80 data" }, + /* 66*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 24, 48, "", 1, "" }, + /* 67*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "________________________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 68*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 36, 36, "", 1, "84 data" }, + /* 69*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 20, 64, "", 1, "" }, + /* 70*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "____________________________________________________________________________________", 0, 36, 36, "", 1, "" }, + /* 71*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 40, 40, "", 1, "90 data" }, + /* 72*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 26, 48, "", 1, "" }, + /* 73*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "__________________________________________________________________________________________", 0, 40, 40, "", 1, "" }, + /* 74*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 40, 40, "", 1, "91 data" }, + /* 75*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 24, 64, "", 1, "" }, + /* 76*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "___________________________________________________________________________________________", 0, 40, 40, "", 1, "" }, + /* 77*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 44, 44, "", 1, "118 data" }, + /* 78*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_DMRE, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 26, 64, "", 1, "118 data" }, + /* 79*/ { BARCODE_DATAMATRIX, -1, -1, -1, DM_SQUARE, -1, { 0, 0, "" }, "______________________________________________________________________________________________________________________", 0, 44, 44, "", 1, "118 data" }, + /* 80*/ { BARCODE_DATAMATRIX, GS1_MODE, -1, -1, -1, -1, { 0, 0, "" }, "[90]12", 0, 10, 10, "", 1, "" }, + /* 81*/ { BARCODE_DATAMATRIX, GS1_MODE | GS1PARENS_MODE, -1, -1, -1, -1, { 0, 0, "" }, "(90)12", 0, 10, 10, "", 1, "" }, + /* 82*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 2, "" }, "1", 0, 12, 12, "", 1, "" }, + /* 83*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 16, 16, "" }, "1", 0, 12, 12, "", 1, "" }, + /* 84*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 1, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 720: Structured Append count '1' out of range (2 to 16)", 1, "" }, + /* 85*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 1, 17, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 720: Structured Append count '17' out of range (2 to 16)", 1, "" }, + /* 86*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 0, 16, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 721: Structured Append index '0' out of range (1 to count 16)", 1, "" }, + /* 87*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 17, 16, "" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 721: Structured Append index '17' out of range (1 to count 16)", 1, "" }, + /* 88*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1001" }, "1", 0, 12, 12, "", 1, "" }, + /* 89*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "A" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 723: Invalid Structured Append ID (digits only)", 1, "" }, + /* 90*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "0" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 724: Structured Append ID1 '000' and ID2 '000' out of range (001 to 254) (ID \"000000\")", 1, "" }, + /* 91*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 725: Structured Append ID1 '000' out of range (001 to 254) (ID \"000001\")", 1, "" }, + /* 92*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1000" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 726: Structured Append ID2 '000' out of range (001 to 254) (ID \"001000\")", 1, "" }, + /* 93*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "001255" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 726: Structured Append ID2 '255' out of range (001 to 254) (ID \"001255\")", 1, "" }, + /* 94*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "255001" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 725: Structured Append ID1 '255' out of range (001 to 254) (ID \"255001\")", 1, "" }, + /* 95*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "255255" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 724: Structured Append ID1 '255' and ID2 '255' out of range (001 to 254) (ID \"255255\")", 1, "" }, + /* 96*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, -1, { 2, 3, "1234567" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 722: Structured Append ID length 7 too long (6 digit maximum)", 1, "" }, + /* 97*/ { BARCODE_DATAMATRIX, -1, -1, -1, -1, READER_INIT, { 2, 3, "1001" }, "1", ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 727: Cannot have Structured Append and Reader Initialisation at the same time", 1, "" }, + /* 98*/ { BARCODE_DATAMATRIX, ESCAPE_MODE, -1, -1, -1, -1, { 2, 3, "1001" }, "[)>\\R05\\GA\\R\\E", 0, 12, 26, "", 1, "Macro05/06 ignored if have Structured Append TODO: error/warning " }, + /* 99*/ { BARCODE_HIBC_DM, -1, -1, -1, -1, -1, { 0, 0, "" }, "1234,67", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 5 in input (alphanumerics, space and \"-.$/+%\" only)", 1, "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + char escaped[8192]; + char cmp_buf[32768]; + 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_options", &symbol); for (i = 0; i < data_size; i++) { @@ -608,8 +679,35 @@ static void test_options(const testCtx *const p_ctx) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (ret < ZINT_ERROR) { - assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, symbol->errtxt); - assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, symbol->errtxt); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (width %d) (%s)\n", + i, symbol->rows, data[i].expected_rows, symbol->width, symbol->errtxt); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", + i, symbol->width, data[i].expected_width, symbol->errtxt); + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, 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[144 * 144 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, 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[144 * 144 + 1]; + 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_errtxt), "i:%d symbol->errtxt %s != %s\n", i, symbol->errtxt, data[i].expected_errtxt); @@ -644,14 +742,19 @@ static void test_reader_init(const testCtx *const p_ctx) { char *comment; }; static const struct item data[] = { - /* 0*/ { BARCODE_DATAMATRIX, UNICODE_MODE, READER_INIT, "A", 0, 10, 10, "EA 42 81 19 A4 53 21 DF", "TODO: Check this" }, + /* 0*/ { BARCODE_DATAMATRIX, UNICODE_MODE, READER_INIT, "A", 0, 10, 10, "EA 42 81 19 A4 53 21 DF", "" }, /* 1*/ { BARCODE_DATAMATRIX, GS1_MODE, READER_INIT, "[91]A", ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 521: Cannot use Reader Initialisation in GS1 mode", "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; - char escaped[1024]; + char escaped[8192]; + char cmp_buf[32768]; + 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_reader_init", &symbol); @@ -678,6 +781,27 @@ static void test_reader_init(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); 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[144 * 144 + 1]; + 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[144 * 144 + 1]; + 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); } @@ -691,7 +815,7 @@ static void test_reader_init(const testCtx *const p_ctx) { #define ZINT_TEST_ENCODING #ifdef ZINT_TEST_ENCODING INTERNAL int dm_encode_test(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci, - const int gs1, unsigned char target[], int *p_tp); + const int last_seg, const int gs1, unsigned char target[], int *p_tp); #endif static void test_input(const testCtx *const p_ctx) { @@ -1044,6 +1168,7 @@ static void test_input(const testCtx *const p_ctx) { int binlens[2] = {0}; unsigned char reduced[1000]; unsigned char *text; + const int last_seg = 1; assert_equal(data[i].expected_rows * data[i].expected_width <= data[i - 1].expected_rows * data[i - 1].expected_width, 1, "i:%d data[i].expected_rows * data[i].expected_width %d > data[i - 1].expected_rows * data[i - 1].expected_width %d\n", i, @@ -1060,7 +1185,7 @@ static void test_input(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode = data[i - 1].input_mode; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, text, length, symbol->eci, gs1, binary[0], &binlen); + ret = dm_encode_test(symbol, text, length, symbol->eci, last_seg, gs1, binary[0], &binlen); assert_zero(ret, "i:%d dm_encode() FAST_MODE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[0] = binlen; @@ -1068,7 +1193,7 @@ static void test_input(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode = data[i].input_mode; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, text, length, symbol->eci, gs1, binary[1], &binlen); + ret = dm_encode_test(symbol, text, length, symbol->eci, last_seg, gs1, binary[1], &binlen); assert_zero(ret, "i:%d dm_encode() minimal ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[1] = binlen; @@ -5611,6 +5736,7 @@ static void test_encode(const testCtx *const p_ctx) { int gs1; int binlen; int binlens[2] = {0}; + const int last_seg = 1; assert_equal(data[i].expected_rows * data[i].expected_width <= data[i - 1].expected_rows * data[i - 1].expected_width, 1, "i:%d data[i].expected_rows * data[i].expected_width %d > data[i - 1].expected_rows * data[i - 1].expected_width %d\n", i, @@ -5619,7 +5745,8 @@ static void test_encode(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode = data[i - 1].input_mode; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, gs1, binary[0], &binlen); + ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, last_seg, gs1, + binary[0], &binlen); assert_zero(ret, "i:%d dm_encode() FAST_MODE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[0] = binlen; @@ -5627,13 +5754,15 @@ static void test_encode(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode = data[i].input_mode; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, gs1, binary[1], &binlen); + ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, last_seg, gs1, + binary[1], &binlen); assert_zero(ret, "i:%d dm_encode() minimal ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[1] = binlen; assert_equal(binlens[1] <= binlens[0], 1, "i:%d binlens[1] %d > binlens[0] %d\n", i, binlens[1], binlens[0]); - assert_equal(binlens[0], binlens[1] + data[i].expected_diff, "i:%d binlens[0] %d != %d binlens[1] (%d) + expected_diff (%d)\n", + assert_equal(binlens[0], binlens[1] + data[i].expected_diff, + "i:%d binlens[0] %d != %d binlens[1] (%d) + expected_diff (%d)\n", i, binlens[0], binlens[1] + data[i].expected_diff, binlens[1], data[i].expected_diff); } #endif @@ -5826,6 +5955,154 @@ static void test_encode_segs(const testCtx *const p_ctx) { "10000011000001110111011000" "11111111111111111111111111" }, + /* 8*/ { BARCODE_DATAMATRIX, UNICODE_MODE | FAST_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("ABCDEFGHIJ"), -1, 3 }, { TU("KL"), -1, 4 }, { TU("MN"), -1, 5 } }, 0, 20, 20, 1, "", + "10101010101010101010" + "10011001100100001111" + "10001100100011101110" + "11001011110111000001" + "10010011100000100100" + "11101010010000010111" + "10101001011101010110" + "10011011001101010011" + "10011101110000001000" + "10111000111110110101" + "10111011100000111000" + "11110000010011100001" + "10110010001100101000" + "10011111100011011111" + "11111011010011010110" + "11011001001000110111" + "11011111100110000110" + "11100100101111100101" + "11000101100101000010" + "11111111111111111111" + }, + /* 9*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("ABCDEFGHIJ"), -1, 3 }, { TU("KL"), -1, 4 }, { TU("MN"), -1, 5 } }, 0, 20, 20, 0, "BWIPP same as FAST_MODE", + "10101010101010101010" + "10001010000100001111" + "10000111000011101110" + "11001001110111010001" + "10010001100000110000" + "11010110010000000011" + "11010111011100110100" + "11011110001001010001" + "11100101110110011000" + "11000000110000110101" + "10001011110001000000" + "11100000110100010101" + "11110011100101111100" + "11011101111010001111" + "11111111010110100110" + "11001110001101010001" + "11010010011000100110" + "10101000101010011101" + "10001111100101101010" + "11111111111111111111" + }, + /* 10*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("AB"), -1, 3 }, { TU("CD"), -1, 4 }, { TU("EF"), -1, 5 } }, 0, 16, 16, 1, "", + "1010101010101010" + "1000100001000101" + "1000110110110010" + "1100110010100101" + "1000001000010010" + "1100001111000111" + "1110100000011110" + "1000011010111001" + "1000001001110100" + "1111101101001001" + "1110111111101010" + "1001000000010011" + "1010010110100000" + "1101001100010101" + "1000000001011010" + "1111111111111111" + }, + /* 11*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("ABC"), -1, 3 }, { TU("DEF"), -1, 4 }, { TU("GHI"), -1, 5 } }, 0, 12, 26, 0, "BWIPP different encodation (1st seg C40)", + "10101010101010101010101010" + "10001000011110001111000011" + "10000101111001000011010000" + "11000000100100110111100111" + "10111000000100111110100110" + "11110011110011010010011001" + "10001000100100010000010000" + "10001110000110000110000001" + "10100001001011000111000110" + "10110110100111010011101111" + "10000100100001011001101100" + "11111111111111111111111111" + }, + /* 12*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("ABCDEF"), -1, 3 }, { TU("GHIJKL"), -1, 4 }, { TU("MNOPQR"), -1, 5 } }, 0, 22, 22, 1, "", + "1010101010101010101010" + "1001100110101101111101" + "1000110010111101010100" + "1100101101111111100001" + "1001001000111100001000" + "1110111000110001011111" + "1010110000001101001100" + "1000011000010101000111" + "1000001111001011101110" + "1111011001111000001001" + "1110101101110111011100" + "1001100011100000011111" + "1111110101001010000010" + "1001011000001100101111" + "1010101010111010100000" + "1111000100011100001111" + "1100000111000010111110" + "1110010000110010010111" + "1111110010101010101010" + "1110001110011001010111" + "1000000100010110101000" + "1111111111111111111111" + }, + /* 13*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("abcdef"), -1, 3 }, { TU("\015*>\015*>"), -1, 4 }, { TU("ghijkl"), -1, 5 } }, 0, 22, 22, 0, "BWIPP different encodation", + "1010101010101010101010" + "1001110110000010100111" + "1000110011011101100100" + "1100101000111110100011" + "1001001000111101111100" + "1110111000110000000001" + "1010110100001101010000" + "1000011000010101000111" + "1000001111001000001110" + "1111011011111010011001" + "1110101111111110100000" + "1001000011101000001011" + "1101000101110001010010" + "1001111000110101010011" + "1011101011101101011000" + "1101000101100000010111" + "1110000101000010110110" + "1110010001101000010111" + "1111110000100110110110" + "1110000111110100001101" + "1100010101011000000000" + "1111111111111111111111" + }, + /* 14*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("abcdefg"), -1, 3 }, { TU("\015*>\015*>\015*"), -1, 4 }, { TU("hijklm"), -1, 5 } }, 0, 22, 22, 0, "BWIPP different encodation", + "1010101010101010101010" + "1000101010011000110001" + "1000011111011010010010" + "1100100000110000111111" + "1001000001000101010000" + "1101000110001000000111" + "1101000010100101101110" + "1101110100010101110111" + "1111101101001000000110" + "1110011111011010101001" + "1111111100001100010000" + "1110110110010010111011" + "1100001111100110011000" + "1100000110000111101101" + "1111000000000101000000" + "1011001101101100000101" + "1110110011011010000000" + "1110100011010111001101" + "1001011100101100101010" + "1000000010001111101111" + "1100011100111001010010" + "1111111111111111111111" + }, }; const int data_size = ARRAY_SIZE(data); int i, j, seg_count, ret; @@ -5889,7 +6166,7 @@ static void test_encode_segs(const testCtx *const p_ctx) { 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 { - ret = testUtilBwippSegs(i, symbol, -1, data[i].option_2, -1, data[i].segs, seg_count, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwippSegs(i, symbol, -1, data[i].option_2, data[i].option_3, data[i].segs, seg_count, NULL, cmp_buf, sizeof(cmp_buf)); assert_zero(ret, "i:%d %s testUtilBwippSegs ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, data[i].expected); @@ -6970,6 +7247,7 @@ static void test_minimalenc(const testCtx *const p_ctx) { int gs1; int binlen; int binlens[2] = {0}; + const int last_seg = 1; testStartSymbol("test_minimalenc", &symbol); @@ -6985,7 +7263,7 @@ static void test_minimalenc(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode |= FAST_MODE; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, gs1, binary[0], &binlen); + ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, last_seg, gs1, binary[0], &binlen); assert_equal(ret, data[i].ret, "i:%d dm_encode() FAST_MODE ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); binlens[0] = binlen; @@ -6993,7 +7271,7 @@ static void test_minimalenc(const testCtx *const p_ctx) { binlen = 0; symbol->input_mode &= ~FAST_MODE; gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; - ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, gs1, binary[1], &binlen); + ret = dm_encode_test(symbol, (unsigned char *) data[i].data, length, symbol->eci, last_seg, gs1, binary[1], &binlen); assert_equal(ret, data[i].ret, "i:%d dm_encode() minimal ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); binlens[1] = binlen; diff --git a/backend/tests/test_dxfilmedge.c b/backend/tests/test_dxfilmedge.c index 8100e7f4..9a8cdbaa 100644 --- a/backend/tests/test_dxfilmedge.c +++ b/backend/tests/test_dxfilmedge.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2024 Antoine Merino + Copyright (C) 2024-2025 Antoine Merino Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -223,7 +223,7 @@ static void test_input(const testCtx *const p_ctx) { /* 0*/ { BARCODE_DXFILMEDGE, -1, "79-1/123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 972: Frame number part length 4 too long (maximum 3)" }, /* 1*/ { BARCODE_DXFILMEDGE, -1, "79-1/1@A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 973: Frame number \"1@A\" is invalid (expected digits, optionally followed by a single \"A\")" }, /* 2*/ { BARCODE_DXFILMEDGE, -1, "012312365", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 974: DX information length 9 too long (maximum 6)" }, - /* 3*/ { BARCODE_DXFILMEDGE, -1, "12-", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 977: Wrong format for DX parts 1 and 2 (expected format: XXX-XX, digits)" }, + /* 3*/ { BARCODE_DXFILMEDGE, -1, "12-", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 977: Wrong format for DX parts 1 and 2 (expected format: NNN-NN, digits)" }, /* 4*/ { BARCODE_DXFILMEDGE, -1, "01234/00A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 980: DX number \"01234\" is incorrect; expected 4 digits (DX extract) or 6 digits (DX full)" }, /* 5*/ { BARCODE_DXFILMEDGE, -1, "0123/0AA", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 983: Frame number \"0AA\" is invalid (expected digits, optionally followed by a single \"A\")" }, /* 6*/ { BARCODE_DXFILMEDGE, -1, "128-0/24", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 978: DX part 1 \"128\" out of range (1 to 127)" }, diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 890972b2..a6baf0b0 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019-2024 Robin Stuart + Copyright (C) 2019-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -601,22 +601,26 @@ const char *testUtilOption3Name(int symbology, int option_3) { const unsigned int high_byte = option_3 == -1 ? 0 : (option_3 >> 8) & 0xFF; if (symbology == BARCODE_DATAMATRIX || symbology == BARCODE_HIBC_DM) { - if ((option_3 & 0x7F) == DM_SQUARE) { - if ((option_3 & DM_ISO_144) == DM_ISO_144) { - name = "DM_SQUARE | DM_ISO_144"; + if (option_3 > 0) { + if ((option_3 & 0x7F) == DM_SQUARE) { + if ((option_3 & DM_ISO_144) == DM_ISO_144) { + name = "DM_SQUARE | DM_ISO_144"; + } else { + name = "DM_SQUARE"; + } + } else if ((option_3 & 0x7F) == DM_DMRE) { + if ((option_3 & DM_ISO_144) == DM_ISO_144) { + name = "DM_DMRE | DM_ISO_144"; + } else { + name = "DM_DMRE"; + } + } else if ((option_3 & DM_ISO_144) == DM_ISO_144) { + name = "DM_ISO_144"; } else { - name = "DM_SQUARE"; + name = (option_3 & 0xFF) ? "-1" : "0"; } - } else if ((option_3 & 0x7F) == DM_DMRE) { - if ((option_3 & DM_ISO_144) == DM_ISO_144) { - name = "DM_DMRE | DM_ISO_144"; - } else { - name = "DM_DMRE"; - } - } else if ((option_3 & DM_ISO_144) == DM_ISO_144) { - name = "DM_ISO_144"; } else { - name = (option_3 & 0xFF) ? "-1" : "0"; + name = option_3 ? "-1" : "0"; } } else if (symbology == BARCODE_QRCODE || symbology == BARCODE_HIBC_QR || symbology == BARCODE_MICROQR || symbology == BARCODE_RMQR || symbology == BARCODE_GRIDMATRIX || symbology == BARCODE_HANXIN) { @@ -2572,7 +2576,7 @@ static char *testUtilBwippEscape(char *bwipp_data, int bwipp_data_size, const ch case 'R': val = 0x1e; /* Record Separator */ break; case 'x': val = d + 2 < de && z_isxdigit(d[1]) && z_isxdigit(d[2]) ? (ctoi(d[1]) << 4) | ctoi(d[2]) : -1; - if (val != -1) d+= 2; + if (val != -1) d += 2; break; case 'd': val = d + 3 < de ? to_int(d + 1, 3) : -1; @@ -2586,7 +2590,14 @@ static char *testUtilBwippEscape(char *bwipp_data, int bwipp_data_size, const ch if (val != -1) d += 3; break; case '\\': val = '\\'; break; - /*case 'u': val = 0; TODO: implement break; */ + case 'u': /* For convenience, only handles ISO/IEC 8859-1 */ + val = d + 4 < de && z_isxdigit(d[1]) && z_isxdigit(d[2]) && z_isxdigit(d[3]) && z_isxdigit(d[4]) + ? (ctoi(d[1]) << 4) | ctoi(d[2]) : -1; + if (val == 0) { /* Only handling Latin-1 so must be zero */ + val = (ctoi(d[3]) << 4) | ctoi(d[4]); + d += 4; + } + break; /*case 'U': val = 0; TODO: implement break; */ case '^': val = -1; break; /* Code 128 special escapes */ default: fprintf(stderr, "testUtilBwippEscape: unknown escape %c\n", *d); return NULL; break; @@ -3274,6 +3285,16 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int if (option_3 != -1) { bwipp_opts = bwipp_opts_buf; } + if (symbol->output_options & READER_INIT) { + memmove(bwipp_data + 5, bwipp_data, strlen(bwipp_data) + 1); + memcpy(bwipp_data, "^PROG", 5); + if (!parsefnc) { + sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%sparsefnc", + strlen(bwipp_opts_buf) ? " " : ""); + bwipp_opts = bwipp_opts_buf; + parse = 1; + } + } } else if (symbology == BARCODE_DOTCODE) { if (option_2 > 0) { sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%scolumns=%d", @@ -3828,7 +3849,7 @@ static const char *testUtilZXingCPPName(int index, const struct zint_symbol *sym { "", -1, 125, }, { "", -1, 126, }, { "", -1, 127, }, - { "", BARCODE_AZRUNE, 128, }, + { "Aztec", BARCODE_AZRUNE, 128, }, { "", BARCODE_CODE32, 129, }, /* Code39 based */ { "", BARCODE_EANX_CC, 130, }, { "", BARCODE_GS1_128_CC, 131, }, @@ -4105,6 +4126,7 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in char *dpd = need_dpd_prefix ? (char *) z_alloca(28 + 1) : NULL; char *pzn = symbology == BARCODE_PZN ? (char *) z_alloca(expected_len + 1 + 1) : NULL; char *dxfe = symbology == BARCODE_DXFILMEDGE ? (char *) z_alloca(expected_len * 2 + 1) : NULL; + char azrune[4]; int ret; int ret_memcmp; @@ -4475,6 +4497,13 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in expected_len = (int) strlen(expected); } } + + } else if (symbology == BARCODE_AZRUNE) { + if (expected_len != 3) { + sprintf(azrune, "%03d", to_int((const unsigned char *) expected, expected_len)); + expected = azrune; + expected_len = 3; + } } if (ret_buf) { diff --git a/backend/tests/tools/run_bwipp_tests.sh b/backend/tests/tools/run_bwipp_tests.sh index 3e4d3d96..30321fd4 100755 --- a/backend/tests/tools/run_bwipp_tests.sh +++ b/backend/tests/tools/run_bwipp_tests.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2021-2024 Robin Stuart +# Copyright (C) 2021-2025 Robin Stuart # SPDX-License-Identifier: BSD-3-Clause # vim: set ts=4 sw=4 et : set -e @@ -34,6 +34,9 @@ run_bwipp_test "test_code16k" "encode" run_bwipp_test "test_code49" "input" run_bwipp_test "test_code49" "encode" run_bwipp_test "test_composite" +run_bwipp_test "test_dmatrix" "buffer" +run_bwipp_test "test_dmatrix" "options" +run_bwipp_test "test_dmatrix" "reader_init" run_bwipp_test "test_dmatrix" "input" run_bwipp_test "test_dmatrix" "encode" run_bwipp_test "test_dmatrix" "encode_segs" diff --git a/backend/tests/tools/run_zxingcpp_tests.sh b/backend/tests/tools/run_zxingcpp_tests.sh index 9d459d13..8d1faa09 100755 --- a/backend/tests/tools/run_zxingcpp_tests.sh +++ b/backend/tests/tools/run_zxingcpp_tests.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2021-2024 Robin Stuart +# Copyright (C) 2021-2025 Robin Stuart # SPDX-License-Identifier: BSD-3-Clause # vim: set ts=4 sw=4 et : set -e @@ -26,9 +26,14 @@ run_zxingcpp_test "test_code" "encode" run_zxingcpp_test "test_code128" run_zxingcpp_test "test_code16k" "input" run_zxingcpp_test "test_code16k" "encode" +run_zxingcpp_test "test_dmatrix" "large" +run_zxingcpp_test "test_dmatrix" "buffer" +run_zxingcpp_test "test_dmatrix" "options" +run_zxingcpp_test "test_dmatrix" "reader_init" run_zxingcpp_test "test_dmatrix" "input" run_zxingcpp_test "test_dmatrix" "encode" run_zxingcpp_test "test_dmatrix" "encode_segs" +run_zxingcpp_test "test_dxfilmedge" "encode" run_zxingcpp_test "test_dotcode" "input" run_zxingcpp_test "test_dotcode" "encode" run_zxingcpp_test "test_dotcode" "encode_segs" diff --git a/docs/README b/docs/README index 0c3a7992..a011d5e7 100644 --- a/docs/README +++ b/docs/README @@ -1,11 +1,11 @@ -% docs/README 2024-12-23 +% docs/README 2025-01-18 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 and Ubuntu 24.04) - wget https://github.com/jgm/pandoc/releases/download/3.6.1/pandoc-3.6.1-1-amd64.deb - sudo dpkg -i pandoc-3.6.1-1-amd64.deb + wget https://github.com/jgm/pandoc/releases/download/3.6.2/pandoc-3.6.2-1-amd64.deb + sudo dpkg -i pandoc-3.6.2-1-amd64.deb For Ubuntu 22.04 (python < 3.12) sudo apt install python3-pip pip install pandoc-tablenos --user @@ -27,9 +27,9 @@ Then On Fedora (tested on Fedora Linux 38 (Workstation Edition) and Fedora Linux 40 (Workstation Edition)) - wget https://github.com/jgm/pandoc/releases/download/3.6.1/pandoc-3.6.1-linux-amd64.tar.gz - tar xf pandoc-3.6.1-linux-amd64.tar.gz - sudo mv -i pandoc-3.6.1/bin/pandoc /usr/local/bin + wget https://github.com/jgm/pandoc/releases/download/3.6.2/pandoc-3.6.2-linux-amd64.tar.gz + tar xf pandoc-3.6.2-linux-amd64.tar.gz + sudo mv -i pandoc-3.6.2/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 d58db9cc..bd496eea 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -333,7 +333,7 @@

Zint Barcode Generator and Zint Barcode Studio User Manual

Version 2.13.0.9

-

December 2024

+

January 2025